我创建了一个简单的WPF项目,在按钮上单击我创建一个带有新窗口的单独线程,并将数据传递给它。在应用程序退出时,我试图安全地关闭该线程/窗口。但是,偶尔会出现波纹管异常,导致应用程序不稳定 所以我的问题是如何优雅地处理这种情况。 THX
在线:
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();
}
答案 0 :(得分:1)
我通常至少会尝试取消BackgroundWorker
事件中的Window.OnClosing
异步操作并捕获待处理的取消。您仍然需要注意ThreadAbortExceptions,但前提是您的异步进程长时间运行。
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();
}
答案 1 :(得分:0)
当您的应用退出时,运行时会自动中止后台线程。通常他们不会抛出ThreadAbortExceptions
(见Foreground and Background threads)
调用调度程序会导致在调度线程上运行方法,但由于您使用的是Invoke()
而不是BeginInvoke()
,因此调度程序需要通知后台线程该方法已完成。我怀疑这是引发异常的地方,但这只是我的猜想。
尝试捕获这样的异常:
try
{
Dispatcher.Invoke(new Action(() =>
{
Close();
}));
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
}
虽然如果在调度线程上引发异常,这可能无济于事。如果这不起作用,请尝试改为BeginInvoke()
。