【发布时间】:2013-10-02 11:18:47
【问题描述】:
我想启动一个线程来监听事件并在后台处理它们。这是我到目前为止所做的:
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();
}
}
有没有更好的方法来解决这个问题?像更适合此目的的线程类?在这种情况下,BackgroundWorker 似乎不是更好的选择...
但是,如果这是一个好方法,那么我就有一个我不太理解的问题。 上述解决方案适用于监听事件并处理它们,但是当调用 Dispose 并将 mKeepHandlingIt 设置为 false 时,退出 while 循环(如果我在循环中放置断点,调试器不会中断)但之后没有代码循环被执行并且 mThread.Join 永远不会返回。基本上......我想知道的是:我如何停止线程,然后确保在它清理之前不要继续?
【问题讨论】:
-
我不会使用
Application.DoEvents,因为它可能会导致启动额外的线程并发生奇怪的事情 - (假设用户单击一个按钮以启动一个进程,然后由于@987654323而再次单击它@ 再次启动该过程!)。由于您在单独的线程上运行东西,因此您不需要它(UI 线程不会阻塞)。如果您可以访问更高版本的 .NET,我会考虑使用 TPL/Task -
HandleIt的代码将在调用事件的同一线程上执行,而不是您创建的线程。 -
运行一个线程来处理(所有?)事件是没有用的。无论如何,GUI 都需要自己的事件。
-
啊,我实际上并没有阅读 Application.DoEvents 究竟做了什么,我只是在一个示例中看到它,有人试图做类似的事情并假设它做了我认为它做的事情......现在我发现在这里调用它是没有意义的。我应该只使用 Thread.Sleep(10) 还是其他东西?
-
我现在有一个任务,它执行与 ProcessEvents 相同的代码,除了 while 循环如下所示: while (!token.IsCancellationRequested) { Thread.Sleep(10); }。我可以完美地启动和停止线程,它会按照我的意愿进行清理,但现在没有处理任何事件! :(
标签: c# multithreading events