2010-04-08 35 views
2

這是我的問題,我有一個有拋出事件的對象的類,在這個事件中,我從我的類拋出一個自定義事件。但不幸的是原始對象從另一個線程拋出事件,所以我的事件也拋出另一個線程。當我的自定義事件嘗試從控件訪問時,這會導致異常。從原始線程調用事件?

下面是一個代碼示例,以更好地理解:

class MyClass 
{ 
    // Original object 
    private OriginalObject myObject; 

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

    public MyClass() 
    { 
     // Original 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); 
    } 
} 

所以,當我的windows窗體我打電話嘗試更新從事件控制StatsUpdated我得到一個跨線程異常導致它被稱爲另一個線。

我想要做的就是將我的自定義事件放在原始類線程上,因此可以在其中使用控件。

任何人都可以幫到我嗎?

回答

3

你可以看看InvokeRequired/Invoke模式。

之前試圖更新一些控制,如果需要調用您檢查並使用Invoke方法,將編組調用已經創造了這個控制線程的護理:

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

更新:

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); 
    } 
} 
+0

調用是一個可以從控制調用,這裏是我想要做的是直接拋出原來的線程(從我的課)對我的事件方法。所以在我的Windows窗體中,我不必關心invoke。我可以直接執行諸如「progressbar.value = arg.progress; – Karnalta 2010-04-08 13:02:29

+0

」在這種情況下,當您調用事件(未在您的代碼段中指定)時,您檢查是否需要調用,並調用parse爲Invoke方法的委託中的事件 – 2010-04-08 13:04:08

+0

我不確定要理解,你說的是我的事件還是originalObject事件? – Karnalta 2010-04-08 13:07:04

0

我不知道,如果是這樣的話,但如果它是安全的,你可以添加到您的表單構造:

Control.CheckForIllegalCrossThreadCalls= false; 

這是僅適用於某些有限情景的「簡單方法」。在我的情況下,就像一個魅力。

+0

是的,但這也是在窗體上使用的解決方案,我想在拋出我的自定義事件之前更正我的課程中的問題。所以我保持我的DLL儘可能簡單,以便在Windows窗體中使用。 – Karnalta 2010-04-08 13:13:05

0

看起來您需要查看SynchronizationContextAsyncOperation類。

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

+0

是的,我正在閱讀這篇文章,它似乎是我正在尋找。 – Karnalta 2010-04-08 13:19:56

+0

我剛剛在本文中嘗試了兩種方法,但在更新進度條時仍然出現交叉線程錯誤。這很奇怪,因爲這個方法看起來很合理。 – Karnalta 2010-04-08 13:34:58