程序挂在Dispatcher.Run()c#上

时间:2014-11-30 08:58:47

标签: c# multithreading dispatcher

我正在使用此代码在单独的线程中运行ProgressBar。

ProgresBarForm viewer = new ProgressBarForm("Wait");    
Thread viewerThread = new Thread(delegate()
    {
        viewer = new ProgressBarForm("Wait");
        viewer.Show();
        System.Windows.Threading.Dispatcher.Run();
    });

viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception
viewerThread.Start();

然后我做了一些长时间的操作,当我完成时我正在调用这段代码:

viewer.BeginInvoke(new Action(() => window.Close()));

它工作得很好但是当我关闭窗口时调试器没有停止。在VS 2012中,我单击“全部中断”按钮,程序挂起就行了

System.Windows.Threading.Dispatcher.Run();

如何关闭此调度程序以退出程序?

提前感谢所有回复。

2 个答案:

答案 0 :(得分:5)

   viewer.BeginInvoke(new Action(() => window.Close()));

这不足以让调度员停下来。您的“查看器”是Winforms表单,而不是WPF窗口。所以正常的关机机制无法正常工作。您必须提供帮助,告诉调度员退出:

   viewer.BeginInvoke(new Action(() => {
       System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown();
       viewer.Close();
   }));

请注意竞争,用户可能会在您有机会调用此代码之前关闭WPF窗口。 DoEvents()苦难的景象比比皆是。所以你可能将线程的IsBackground属性设置为 true 。并且要注意在工作线程上显示UI的问题,您必须仔细制作“进度”表单,以便它不使用工具箱中的任何危险控件。那些使用SystemEvents类的。或者你可以调试死锁like this

如果你让你的UI线程做繁重的工作,这将永远更好,更可靠。让它照顾只是 UI,在工作线程中进行繁重的工作。

答案 1 :(得分:3)

因为你的线程是一个前台线程,这足以让你的进程保持活跃状态​​。

通过设置viewerThread.IsBackGround = true使其成为后台线程,以便它无法使您的进程保持活动状态。

或者在关闭窗口的回调中,只需在关闭窗口后调用Dispatcher.InvokeShutdown