2012-05-05 27 views
1

我可以提出一個靜態事件線程安全嗎? (我不完全確定這意味着什麼)。 整個事情是音頻應用程序的一部分,所以我至少有音頻處理線程和UI線程。如何在C#中引發一個靜態事件線程安全?

的RaisePrintEvent會從非託管的C代碼,其處理音頻和其他消息調用。提升事件的調用可以從音頻處理線程和UI線程中發生。

public static event ProcessPrint Print = delegate {}; 

private static void RaisePrintEvent(string e) 
{ 
    Print(e); 
} 

我怎樣才能確保事件調用是同步的?或者可能只是在主線程中調用..

編輯:請在這裏閱讀a smart solution

回答

3

您必須確保UI操作全部在主/ UI線程上執行。

最好的方法是將消息從音頻線程排列成某種形式的隊列,並從主UI線程(例如​​事件)中將其排隊並顯示出來。

Invoke()不會讓你遠,因爲你在音頻處理時間將被打破。如果你嘗試了它,並且你正在用GUI進行某些操作,那麼你可能會在音頻中出現亂碼,因爲Invoke()在其他線程上的某些內容會一直BLOCK,直到其他線程處理用來執行調用的窗口消息爲止。在引擎蓋下'。

如果您不明白上面的部分或全部內容,只是嘗試使用隊列中的消息。

+0

+1表示線程之間進行通信的隊列。 – spender

+0

@spender沒有別的辦法,在那裏:) –

+0

你認爲使用SynchronizationContext是正確的方法嗎? on可以設置一個Synchronization上下文,這個事件將在這個上下文中被調用。如果它是空的,只是沒有誠實地調用 – thalm

2

您需要處理程序複製到一個局部變量,以避免出現競爭狀況時,從事件的另一個線程取消訂閱,當你調用它(見here瞭解詳細信息):

private static void RaisePrintEvent(string e) 
{ 
    var handler = Print; 
    if (handler != null) 
    { 
     handler(e); 
    } 
} 

如果你想該事件一次只能由一個線程提出,只需將該呼叫置於鎖定中:

private static readonly object _printLock = new object(); 
private static void RaisePrintEvent(string e) 
{ 
    lock(_printLock) 
    { 
     var handler = Print; 
     if (handler != null) 
     { 
      handler(e); 
     } 
    } 
} 
+0

+1 var'handler = Print;' –

+0

k,競爭條件也可以通過添加一個簡單的處理程序來解決,請參閱編輯。 – thalm

+0

@thalm,是的,但我不太喜歡這種方法......它對我來說就像一個骯髒的黑客;) –