开发者

Call event from original thread?

Here is my problem, I have a class which have a object who throw an event and in this event I throw a custom event from my class. But unfortunately the original object throw the event from another thread and so my event is also throw on another thread. This cause a exception when my custom event try to access from controls.

Here is a code sample to better understand :

class MyClass
{
    // Original object
    private OriginalObject myObject;

    // My event
    public delegate void StatsUpdatedDelegate(object sender, StatsArgs args);
    public event StatsUpdatedDelegate StatsUpdated;

    public MyClass()
    {
        // Origina开发者_JAVA技巧l object event
        myObject.DoSomeWork();
        myObject.AnEvent += new EventHandler(myObject_AnEvent);
    }

    // This event is called on another thread while myObject is doing his work
    private void myObject_AnEvent(object sender, EventArgs e)
    {
        // Throw my custom event here
        StatsArgs args = new StatsArgs(..........);
        StatsUpdated(this, args);
    }
}

So when on my windows form I call try to update a control from the event StatsUpdated I get a cross thread exception cause it has been called on another thread.

What I want to do is throw my custom event on the original class thread, so control can be used within it.

Anyone can help me ?


You may take a look at the InvokeRequired/Invoke pattern.

Before trying to update some control you check if invoke is required and use the Invoke method which will take care of marshaling the call to the thread that has created this control:

Control ctrlToBeModified = // 
if (ctrlToBeModified.InvokeRequired)
{
    Action<Control> del = (Control c) => 
    { 
        // update the control here
    };
    ctrlToBeModified.Invoke(del, ctrlToBeModified);
}

UPDATE:

private void myObject_AnEvent(object sender, EventArgs e)
{
    // Throw my custom event here
    StatsArgs args = new StatsArgs(..........);
    Control control = // get reference to some control maybe the form or 'this'
    if (control.InvokeRequired)
    {
        Action<Control> del = (Control c) => 
        { 
            // This will invoke the StatsUpdated event on the main GUI thread
            // and allow it to update the controls
            StatsUpdated(this, args);
        };
        control.Invoke(del);
    }
}


I am not sure if this is the case, but if it is safe you may add to your form constructor:

Control.CheckForIllegalCrossThreadCalls= false;

This is the "easy way" that only applies in some limited scenarios. In my case works like a charm.


It looks like you need to look into the SynchronizationContext or AsyncOperation classes.

http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜