Multithreaded delegates / events

I am trying to disable parts of the UI in a .NET application based on a poll done on a background thread. The background thread checks to see if everything is open and the global database connection is operational.

What I need to do, and would prefer to do it without polling on the UI thread, is to add an event handler that can be raised by a background thread if the connection state changes. Thus, any form can have a handler that will disable those parts of the user interface that require a connection to the function.

Attempting to directly declare an event in a class that contains the subtext of a thread, and recreate an event on a background thread that causes cross-thread execution errors with respect to accessing UI controls from other threads.

Obviously there is a correct way to do this, but we have limited experience with events (mostly with a single application thread) and almost none with delegates. I've read the documentation and examples for delegates and it looks like it's closer to what we need, but I'm not sure how to get it to work in this case.

The app is written mostly in VB.NET, but an example or help in C # is good too.

+2


a source to share


3 answers


You can marshal the event assembly back to the UI thread. Since this is probably (if you design well) run from a separate class, my recommendation would be to pass a copy of the current SynchronizationContext to your class, which handles the background process.

Here is some sample code in C #:

public class BackgroundWork
{
    public SynchronizationContext Context { get; private set; }
    public BackgroundWork(SynchronizationContext context)
    {
        this.Context = context;
    }

    // Thread handler, etc...

    // Method to raise event
    void RaiseEvent()
    {
         Context.Post( (state) =>
         {
             // Raise the event
             this.ConnectionStatusChanged(this, EventArgs.Empty);
         }, null);
    }
}

      



Then when you create the class (on the UI thread), pass the current context to it:

BackgroundWork worker = new BackgroundWork(SynchronizationContext.Current); // This passes the UI thread context...
worker.Start();

      

(This, by the way, is the same technique as the BackgroundWorker class , so it works the same for both Windows Forms and WPF ...)

+2


a source


You solve the cross-thread execution error with Control.Dispatcher.Invoke

:

public void EnventHandlerMethod(object sender, EventArgs e)
{
    myLabel.Dispatch.Invoke(new Action(() => { myLabel.Content = "Updated"; }));
}

      



The signature of the event handler can vary depending on the event you are handling. Of course, if you are just changing the control on a different thread, you only need the body of the above method.

Also this (I think) assumes .NET 3.5

0


a source


Try the Invoke method of the control you want to change, or some kind of control, and supply a small function to do your work you want. Or look BeginInvoke

for asynchronous execution.

Just be wary of threading issues, changing variables that the "main" thread changes, etc.

0


a source







All Articles