简体   繁体   English

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

[英]How to raise a static event thread safe in C#?

Can i raise a static event thread safe? 我可以提出一个安全的静态事件线程吗? (i am not entirely sure what that even means.) The whole thing is part of an audio application, so i have (at least) the audio processing thread and the UI thread. (我并不完全确定这意味着什么。)整个事情都是音频应用程序的一部分,因此(至少)我具有音频处理线程和UI线程。

The RaisePrintEvent gets invoked from unmanaged C code which processes the audio and other messages. RaisePrintEvent从处理音频和其他消息的非托管C代码中调用。 The call to raise the event can happen from the audio processing thread and the UI thread. 引发事件的调用可以从音频处理线程和UI线程进行。

public static event ProcessPrint Print = delegate {};

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

How can i make sure, that the event call is synchronized? 我如何确保事件调用已同步? Or maybe just invoked in the main thread.. 或者也许只是在主线程中调用。

EDIT : read on here for a smart solution . 编辑 :在这里阅读一个智能的解决方案

You must ensure that the UI operations are all executed on the main/UI thread. 您必须确保所有UI操作都在main / UI线程上执行。

Best way would be to queue the messages into some form of queue from the audio thread and dequeue and display it from main UI thread, from Forms.Timer event, for example. 最好的方法是将消息从音频线程排队到某种形式的队列中,并从主UI线程(例如Forms.Timer事件) Forms.Timer其出队并显示出来。

Invoke() won't get you far because your timing in the audio processing will be broken. Invoke()不会使您走得太远,因为您在音频处理中的时间安排将会中断。 If you try it, and you are doing something with your GUI, you'll probably get jerking in the audio, since Invoke()-ing something on other thread will BLOCK until other thread process the window message that is used to do Invoke 'under the hood'. 如果您尝试了该操作,并且正在使用GUI进行操作,则音频中可能会出现抖动,因为在其他线程上执行Invoke()-在其他线程上执行操作会阻塞,直到其他线程处理用于执行Invoke'的窗口消息为止在幕后”。

If you don't understand some or all of the above, just try to use queue for the messages. 如果您不了解上述部分或全部内容,请尝试对消息使用队列。

You need to copy the handler to a local variable, to avoid a race condition when another thread unsubscribes from the event while you're calling it (see here for details): 您需要将处理程序复制到局部变量,以避免在调用该事件时另一个线程取消订阅该事件时出现争用情况(有关详细信息,请参见此处 ):

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

If you want the event to be raised by only one thread at a time, just put the call in a lock: 如果您希望一次仅由一个线程引发事件,只需将调用置于锁中即可:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM