[英]Executing Task freezes GUI when running from event raised by other Task, but not from Button.Click
我在一个单独的项目中有一些任务可以异步执行内容。 现在一切都可以按预期工作几个月了:
但是有一项新要求,要求我必须在编程后直接阅读版本,而无需任何用户交互。
我的第一个想法是从编程的“ Ended”事件中调用ReadVersion
。 但是,这样做时,UI会冻结。 忙碌指示器挂在“正在编程”状态,在读取版本之前无法移动窗口。 通过ReadVersion
调用ReadVersion
,单击不会冻结GUI。
ProjectLogic:
protected void ProgramImage()
{
this.OnProgrammingStarted(new EventArgs());
this.taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(this.ProgramImageAsync)
.ContinueWith(
t =>
{
if (t.IsFaulted)
{
this.TaskExceptionHandlerProgramming(t);
}
else
{
this.ProgramImageAsyncDone();
}
},
this.taskScheduler);
}
public void ReadVersion()
{
this.OnVersionReadingStarted(new EventArgs());
this.taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<string>.Factory.StartNew(ReadVersionAsync).ContinueWith(
t =>
{
if (t.IsFaulted)
{
this.TaskExceptionHandlerVersionReading(t);
}
else
{
this.ReadVersionAsyncDone(t.Result);
}
},
this.taskScheduler);
}
GUI:
private void OnProgrammingExecuted(object sender, WorkExecutedEventArgs e)
{
if (e.Error != null)
{
// Logging + messagebox
this.BiProgramming.IsBusy = false;
this.Restart();
return;
}
if (!e.Success)
{
// Logging + messagebox
this.BiProgramming.IsBusy = false;
this.Restart();
return;
}
this.BiProgramming.IsBusy = false; // Stops busyindicator
BL.ReadVersion(); // Window freezes and busyIndicator stays visible.
}
private void BtnReadVersionClick(object sender, RoutedEventArgs e)
{
BL.ReadVersion(); // works as expected
}
编辑
OnProgrammingExecuted
是从ProgramImageAsyncDone
内部引发事件时执行的方法。
从UI线程中调用ProgramImage
方法。 而且,如果我没记错的话,这意味着TaskSheduler.FromCurrentSynchronizationContext
确保ProgramImageAsyncDone
(或TaskExceptionHandlerProgramming
)在UI线程上运行。
它以前没有引起任何问题,这一事实增强了我的看法。
问题出在我必须添加的行中:对ReadVersion
的调用。 添加此行后,UI冻结。 但是从按钮调用此方法。单击不会冻结UI。
在寻找解决方案时,我遇到了Task.Run与Task.Factory.StartNew,并且我已经使用Task.Run
重新编写了代码,以查看这是否解决了我的问题。 显然是的。
更改的代码:
protected void ProgramImage()
{
this.OnProgrammingStarted(new EventArgs());
this.taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Run(() => this.ProgramImageAsync()).ContinueWith(
t =>
{
if (t.IsFaulted)
{
this.TaskExceptionHandlerProgramming(t);
}
else
{
this.ProgramImageAsyncDone();
}
},
this.taskScheduler);
}
public void ReadVersion()
{
this.OnVersionReadingStarted(new EventArgs());
Task.Run(() => ReadVersionAsync()).ContinueWith(
t =>
{
if (t.IsFaulted)
{
this.TaskExceptionHandlerVersionReading(t);
}
else
{
this.ReadVersionAsyncDone(t.Result);
}
},
this.taskScheduler);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.