mog*_*izx 4 c# events multithreading
我想启动一个侦听事件并在后台处理它们的线程.这是我到目前为止所做的:
private Thread mThread;
private bool mKeepHandlingIt;
private void Init()
{
mKeepHandlingIt = true;
mThread = new Thread(ProcessEvents);
mThread.SetApartmentState(ApartmentState.STA);
mThread.Start();
}
private void ProcessEvents()
{
StaticClass.CoolEvent += HandleIt;
StaticClass.StartDoingStuff();
while (mKeepHandlingIt)
{
Application.DoEvents();
}
StaticClass.StopDoingStuff();
StaticClass.CoolEvent -= HandleIt;
}
private void HandleIt(object sender, EventArgs e)
{
//Handles it
}
protected override void Dispose()
{
if (mThread != null)
{
mKeepHandlingIt = false;
mThread.Join();
}
}
Run Code Online (Sandbox Code Playgroud)
有更好的方法吗?就像一个更适合这个目的的线程类?在这种情况下,BackgroundWorker似乎不是更好的选择......
如果这是一个很好的方法,那么我有一个我无法理解的问题.上面的解决方案适用于侦听事件和处理它们,但是当调用Dispose并且mKeepHandlingIt设置为false时,退出while循环(如果我在循环中放置断点,调试器不会中断)但是后面没有代码执行循环并且mThread.Join永远不会返回.基本上......我想知道的是:如何停止线程,然后确保在清理之前不要继续?
这段代码有很多问题.首先,它遭受了事件处理程序在该工作线程上运行的错觉.这不是事件的工作方式,处理程序在与触发事件的代码完全相同的线程上运行..NET中没有机制让它跳转到另一个线程.
您可以使用调试器的Debug + Windows + Threads窗口看到的东西.在Init()方法上设置一个断点,在事件处理程序上设置一个断点.当它们中断时,切换到该调试器屏幕并记下所选的线程.
使用Application.DoEvents()非常危险.但不是这里,线程没有创建任何窗口,所以没有事件要做.相反,该线程将只燃烧100%的核心,而不是完成任何事情.
mKeepHandlingIt变量通常不会按照您的希望执行.当您在32位计算机上运行代码的Release版本时,线程将永远不会将其设置为false,因此线程将永远不会退出.而Thread.Join()将陷入僵局.这是由抖动优化器引起的,它将bool变量存储在cpu寄存器中,并且永远不会从内存中重新加载它.您必须声明变量volatile以防止进行此优化.哪个是hack,你应该总是使用适当的同步对象来发送线程信号,这里适合使用AutoResetEvent.
只需删除此代码,它对您没有帮助.