如何在C#中引发静态事件线程安全?

时间:2012-05-05 21:10:10

标签: c# multithreading events

我可以提高静态事件线程安全吗? (我不完全确定这甚至意味着什么。) 整个事情是音频应用程序的一部分,所以我(至少)有音频处理线程和UI线程。

从处理音频和其他消息的非托管C代码调用RaisePrintEvent。提升事件的调用可以从音频处理线程和UI线程发生。

public static event ProcessPrint Print = delegate {};

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

如何确保事件调用已同步?或者可能只是在主线程中调用..

编辑:请在此处阅读a smart solution

2 个答案:

答案 0 :(得分:3)

您必须确保UI操作全部在主/ UI线程上执行。

最好的方法是将消息从音频线程排队到某种形式的队列中,然后从主用户界面线程出发并从Forms.Timer事件中显示出来。

Invoke()不会让你走得太远,因为你的音频处理时间将被打破。如果您尝试它,并且您正在使用GUI执行某些操作,则可能会在音频中出现抖动,因为Invoke() - 在其他线程上执行某些操作将会阻塞,直到其他线程处理用于执行Invoke的窗口消息为止在引擎盖下'。

如果您不理解上述部分或全部内容,请尝试使用队列进行消息。

答案 1 :(得分: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);
        }
    }
}