我可以提高静态事件线程安全吗? (我不完全确定这甚至意味着什么。) 整个事情是音频应用程序的一部分,所以我(至少)有音频处理线程和UI线程。
从处理音频和其他消息的非托管C代码调用RaisePrintEvent。提升事件的调用可以从音频处理线程和UI线程发生。
public static event ProcessPrint Print = delegate {};
private static void RaisePrintEvent(string e)
{
Print(e);
}
如何确保事件调用已同步?或者可能只是在主线程中调用..
编辑:请在此处阅读a smart solution。
答案 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);
}
}
}