线程传递数据和窗口closures

我创build了一个简单的WPF项目,在button单击我创build一个单独的线程与新窗口,并将数据传递给它。 在应用程序退出时,我试图closures该线程/窗口。 但是,偶尔会遇到以下exception,这会导致应用程序不稳定。
所以我的问题是如何妥善处理这种情况。 谢谢

在线:

Dispatcher.Invoke(new Action(() => 

我有

 A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll Additional information: Thread was being aborted. 

我的视图有以下代码:

构造函数

 public MyView(ConcurrentQueue<MyItem> actionReports, ManualResetEvent actionCompletedEvent, string actionName) { _actionReports = actionReports; _actionCompletedEvent = actionCompletedEvent; _actionName = actionName; InitializeComponent(); DataContext = this; this.Loaded += MyView_Loaded; } void MyView_Loaded(object sender, RoutedEventArgs e) { var worker = new BackgroundWorker(); worker.DoWork += (o, ea) => { while (true) { if (_actionCompletedEvent.WaitOne(0)) { // Issue Dispatcher.Invoke(new Action(() => { Close(); })); Thread.Sleep(100); } while (!_actionReports.IsEmpty) { // Do some stuff } } }; worker.RunWorkerAsync(); } 

窗口的初始化

 public WindowLauncher(ManualResetEvent actionCompletedEvent, ManualResetEvent reportWindowClosedEvent, string actionName) { _actionCompletedEvent = actionCompletedEvent; _reportWindowClosedEvent = reportWindowClosedEvent; _actionName = actionName; Thread thread = new Thread(new ThreadStart(() => { _reportWindow = new MyView(_messageQueue, _actionCompletedEvent, actionName); _reportWindow.Show(); // InvokeShutdown to terminate the thread properly _reportWindow.Closed += (sender, args) => { _reportWindow.Dispatcher.InvokeShutdown(); }; _resetEvent.Set(); Dispatcher.Run(); })); thread.Name = "MyWindowThread"; thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); } 

我通常至less会尝试取消Window.OnClosing事件中的BackgroundWorkerasynchronous操作,并捕获挂起的取消。 你仍然需要注意ThreadAbortExceptions但是只有当你的asynchronous进程是长时间运行的。

 private BackgroundWorker _worker; private void MyView_Loaded(object sender, RoutedEventArgs e) { _worker = new BackgroundWorker(); _worker.WorkerSupportsCancellation = true; _worker.DoWork += (o, ea) => { while (true) { if (_actionCompletedEvent.WaitOne(0)) { if (_worker.CancellationPending) { ea.Cancel = true; return; } // Issue Dispatcher.Invoke(new Action(() => { Close(); })); Thread.Sleep(100); } while (!_actionReports.IsEmpty) { // Do some stuff } } }; } protected override void OnClosing(CancelEventArgs e) { _worker.CancelAsync(); } 

后台线程会在您的应用退出时由运行时自动中止。 通常他们不会抛出ThreadAbortExceptions (请参阅前台和后台线程 )

调用调度程序会导致在调度线程上运行一个方法,但由于您使用了Invoke()而不是BeginInvoke() ,调度程序需要通知后台线程该方法已完成。 我怀疑这是例外情况,但这只是我自己的猜想。

尝试捕捉像这样的exception:

 try { Dispatcher.Invoke(new Action(() => { Close(); })); } catch (ThreadAbortException) { Thread.ResetAbort(); } 

虽然这可能无助于如果在调度线程上引发exception。 如果这不起作用,请尝试BeginInvoke()

顺便说一句,如果你在调用lambda的开始处延迟某些延迟,并且closures应用程序,那么你可以更容易地重现这个bug。 这意味着后台线程将在lambda完成时被中止。