我希望在关闭基于MVVM的WPF应用程序时同步执行一系列操作。
现在我在任务中使用Task和Dispatcher.Invoke
来向用户显示消息。
问题是当我在Dispatcher.Invoke
函数中使用myfunction
方法时,应用程序会卡在那里。我知道当我使用除闭合事件以外的这些功能时,此功能正常工作。
因此在应用程序的Close事件中使用Dispatcher.Invoke
方法是否有任何问题。我该如何解决这个问题?
/// <summary>
/// Main window closing
/// </summary>
private void MainWindowClosing(object args)
{
var task1 = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
myfunction();
}).ContinueWith((cc) => { });
task1.Wait();
}
private void myfunction()
{
//my serries of operation will come here.
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show("test");
}));
}
答案 0 :(得分:2)
您在此处创建Deadlock 。即使将代码放在按钮点击处理程序中,它也不会起作用。
您正在使用task1.Wait()
创建任务并等待任务。因此, UI调度程序正在等待任务完成,然后才能处理任何其他消息。
同时你从任务调用UI调度程序上的一个操作,这个操作太同步了
App.Current.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show("test");
}));
但由于UI调度程序仍在等待任务完成,因此无法同步调用任何方法。因此 DEADLOCK (彼此等待)。
如果你想同步调用任务而没有关闭窗口,你可以使用以下步骤来实现:
e.Cancel = true
取消关闭事件,并在完成后从任务本身手动提升关闭事件。相关代码:
bool closeInitiated = false;
private void poc_Closing(object sender, CancelEventArgs e)
{
if (!closeInitiated)
{
var task1 = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
myfunction();
}).ContinueWith((cc) => { });
closeInitiated = true;
e.Cancel = true;
}
}
private void myfunction()
{
App.Current.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show("test");
Close();
}));
}
答案 1 :(得分:0)
我认为问题出在task1.Wait();完成此UI Thread Wait and DeadLock
我希望这会有所帮助。
答案 2 :(得分:0)
我遇到了同样的问题,我发现问题是我调用的任务在单击“关闭”按钮后已经关闭了一秒钟,所以当调用函数需要更长时间时 - 它可能会崩溃。
如果您仍想执行此功能,我使用的是BeginInvoke
而不是Invoke
,而且效果正常。
这是我的代码:
if (app.Current.Dispatcher.CheckAccess()) //doesn't need to be invoked
myFunction();
else //coming from another thread need invoker
{
//at exiting program this task might already be canceled, so make sure it's not
if (!app.Current.Dispatcher.HasShutdownFinished)
app.Current.Dispatcher.Invoke(myFunction());
else
app.Current.Dispatcher.BeginInvoke(myFunction());