Why does NotifyIcon not set SynchronizationContext

2019-07-23 01:04发布

问题:

Consider this WinForms program:

Module Main
    Dim notifyicon As New System.Windows.Forms.NotifyIcon
    'Dim dummycontrol As New System.Windows.Forms.Control

    Public Sub Main()
        If (System.Threading.SynchronizationContext.Current Is Nothing) Then
            MessageBox.Show("Nothing")
        Else
            MessageBox.Show("Something")
        End If
    End Sub
End Module

NotifyIcon is a WinForm control, and requires a message loop, so why will declaring dummycontrol (or any WinForms control) set a SynchronizationContext, but the NotifyIcon does not?

回答1:

This is something you can discover from the Reference Source, the synchronization provider is installed by the WindowsFormsSynchronizationContext.InstallIfNeeded() method. Look at the references to see when it is called:

  • Application.Run()
  • The Control class constructor
  • The helper method that dispatches Begin/Invoke() calls (won't happen).

NotifyIcon is derived from Component, not Control, so never hits one of those 3 bullets. It is a thin wrapper around the Shell_NotifyIcon() winapi function. I suppose you can call it bug that its constructor doesn't call InstallIfNeeded() but that's a bit of a stretch, you always must call Application.Run() to make it functional so you'll always hit the 1st bullet. Just beware initialization order.