Hed*_*ley 1 .net c# user-interface winforms task-parallel-library
我刚刚将我的主应用程序从.NET 2.0升级到.NET 4.5,并且我正在尝试使用C#5.0提供的更高级的语言功能.
我目前正在重新编写一些旧的异步代码例程,这些例程使用"MethodInvoker"/"AsyncCallback"(以保持UI流畅)与Tasks.
这是旧代码遵循的模式......
void RefreshScreen()
{
// code to prepare UI for updating
...
MethodInvoker del = new MethodInvoker(LoadData);
del.BeginInvoke(new AsyncCallback(LoadData_Callback), null);
}
void LoadData()
{
// perform data calculations
}
void LoadData_Callback(IAsyncResult ar)
{
AsyncResult res = (System.Runtime.Remoting.Messaging.AsyncResult)ar;
MethodInvoker del = (MethodInvoker)res.AsyncDelegate;
try
{
del.EndInvoke(ar); // <- throw exception if one occurred during async operation
}
catch (Exception E)
{
// handle exception
}
// Update the UI: if (this.InvokeRequired) {...}
}
Run Code Online (Sandbox Code Playgroud)
好的 - 所以这是我到目前为止基于任务的等价物: -
void RefreshScreen()
{
// code to prepare UI for updating
...
Task.Run(() => LoadData()).ContinueWith((t) => LoadData_Callback(t));
}
void LoadData()
{
// perform data calculations
}
void LoadData_Callback(Task t)
{
try
{
t.Wait(); // <- throw exception if one occurred during async operation
}
catch (Exception E)
{
// handle exception
}
// Update the UI: if (this.InvokeRequired) {...}
}
Run Code Online (Sandbox Code Playgroud)
所以这是我的问题......我已经阅读了很多关于异常处理与任务的文章和资源,其中一些讨论了检查" task.IsCompleted "和/或" task.Status "等内容,以及分支到多个ContinueWiths使用TaskContinuationOptions.
我试图让它尽可能简单,所以在ContinueWith方法中简单地调用" task.Wait() ",在那里捕获一个Exception(根据上面的代码)或者是否有更好的方法是可以接受的做法去做这个?
非常感谢!
更新和答案
为了澄清,我应该解释原始代码在WinForms应用程序中使用,目标是在长DB操作(或任何其他长进程)期间保持UI响应,通过在不同的线程上异步运行它们.
Silas和Servy指出,自从切换到C#5.0后,我应该使用async/await,所以这是我选择使用的代码,类似于上面的例子......
async Task RefreshScreen()
{
// code to prepare UI for updating
...
try
{
await Task.Run(() => LoadData());
}
catch (Exception E)
{
// handle exception
}
// Update the UI: WITHOUT the need to check "this.InvokeRequired"
return Task.FromResult(0);
}
Task LoadData()
{
// perform data calculations
return Task.FromResult(0);
}
Run Code Online (Sandbox Code Playgroud)
这个代码比" MethodInvoker "或" Task "方法至少有两个好处: -
(1)它更清晰
(2)Ater从await返回,后续代码在UI线程上,所以没有必要faff " if(this.InvokeRequired){...} "(请参阅Stephen Cleary的博客了解更多相关信息).
原来的问题怎么样?是否可以使用Wait来捕获ContinueWith中的异常?
我想这是一个有争议的问题,因为async/await显然是要走的路,但经过进一步的研究,答案是肯定的,这样做是可以的!
您可以用以下内容替换所有这些内容:
public async Task LoadData()
{
// do something DB intensive
}
public async Task HandleLoadExceptions()
{
try
{
await LoadData();
}
catch (Exception E)
{
// handle exception
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
261 次 |
| 最近记录: |