我在一个单独的项目中有一些任务可以异步执行。 这一切都按预期工作了几个月了:
但是一项新要求规定我必须在编程后直接阅读该版本,而无需任何用户交互。
我的第一个想法是从编程的“结束”事件中调用ReadVersion
。
但是,这样做时,UI会冻结。
busyindicator挂起“编程”状态,并且在读取版本之前不能移动窗口。
从按钮调用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
可以确保{-1}}(或ProgramImageAsyncDone
)在UI线程上运行。
事先没有引起任何问题,这加强了我的意见。
问题在于我必须添加的行:对TaskExceptionHandlerProgramming
的调用。
添加此行后,UI处于冻结状态。
但是从按钮调用此方法。单击不会冻结UI。
答案 0 :(得分:0)
在搜索解决方案时,我遇到了Task.Run vs 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);
}