Force multi-threaded VB.NET class to display results on a single form

前端 未结 4 1811
走了就别回头了
走了就别回头了 2020-12-22 07:10

I have a windows form application that uses a Shared class to house all of the common objects for the application. The settings class has a collection of objects that do thi

相关标签:
4条回答
  • 2020-12-22 07:41

    I think it is a threading problem too. Are you using Control.Invoke() in your event handler? .NET usually catches violations when you debug the app but there are cases it can't. NotifyIcon is one of them, there is no window handle to check thread affinity.

    Edit after OP changed question:

    A classic VB.NET trap is to reference a Form instance by its type name. Like Form1.NotifyIcon1.Something. That doesn't work as expected when you use threading. It will create a new instance of the Form1 class, not use the existing instance. That instance isn't visible (Show() was never called) and is otherwise dead as a doornail since it is running on thread that doesn't pump a message loop. Seeing a second icon appear is a dead give-away. So is getting InvokeRequired = False when you know you are using it from a thread.

    You must use a reference to the existing form instance. If that is hard to come by (you usually pass "Me" as an argument to the class constructor), you can use Application.OpenForms:

      Dim main As Form1 = CType(Application.OpenForms(0), Form1)
      if (main.InvokeRequired)
        ' etc...
    
    0 讨论(0)
  • 2020-12-22 07:53

    Use Control.InvokeRequired to determine if you're on the proper thread, then use Control.Invoke if you're not.

    0 讨论(0)
  • 2020-12-22 07:58

    You should look at the documentation for the Invoke method on the Form. It will allow you to make the code that updates the form run on the thread that owns the form, (which it must do, Windows forms are not thread safe). Something like Private Delegate Sub UpdateStatusDelegate(ByVal newStatus as String)

    Public sub UpdateStatus(ByVal newStatus as String) If Me.InvokeRequired Then Dim d As New UpdateStatusDelegate(AddressOf UpdateStatus) Me.Invoke(d,new Object() {newStatus}) Else 'Update the form status End If

    If you provide some sample code I would be happy to provide a more tailored example.

    Edit after OP said they are using InvokeRequired.

    Before calling InvokeRequired, check that the form handle has been created, there is a HandleCreated property I belive. InvokeRequired always returns false if the control doesn't currently have a handle, this would then mean the code is not thread safe even though you have done the right thing to make it so. Update your question when you find out. Some sample code would be helpful too.

    0 讨论(0)
  • 2020-12-22 08:01

    in c# it looks like this:

    private EventHandler StatusHandler = new EventHandler(eventHandlerCode)
    void eventHandlerCode(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(StatusHandler, sender, e);
            }
            else
            {
              //do work
            }
        }
    
    0 讨论(0)
提交回复
热议问题