Kob*_*ari 7 c# wpf task task-parallel-library
当在工作线程上调用的方法需要在UI线程上运行代码并在执行其他操作之前等待它完成时,可以这样做:
public int RunOnUi(Func<int> f)
{
int res = Application.Current.Dispatcher.Invoke(f);
return res;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我想用任务做什么呢?有没有办法让RunOnUi方法创建一个在UI上启动并返回它的任务,以便调用者(在工作线程上运行)可以等待它?符合以下签名的东西:public Task<int> StartOnUi(Func<int> f)?
一种方法如下:
public Task<int> RunOnUi(Func<int> f)
{
var task = new Task<int>(f);
task.Start(_scheduler);
return task;
}
Run Code Online (Sandbox Code Playgroud)
这里,假设_schduler持有ui TaskScheduler.但是我不太习惯于创建"冷"任务并使用start方法来运行它们.这是"推荐"的方式还是有更优雅的方式来做到这一点?
只需使用InvokeAsync而不是Invoke返回函数Task<int>内部DispatcherOperation<int>返回.
//Coding conventions say async functions should end with the word Async.
public Task<int> RunOnUiAsync(Func<int> f)
{
var dispatcherOperation = Application.Current.Dispatcher.InvokeAsync(f);
return dispatcherOperation.Task;
}
Run Code Online (Sandbox Code Playgroud)
如果您无法访问.NET 4.5,则会更复杂一些.您将需要使用BeginInvoke和TaskCompletionSource包装的DispaterOperation是BeginInvoke返回
public Task<int> RunOnUi(Func<int> f)
{
var operation = Application.Current.Dispatcher.BeginInvoke(f);
var tcs = new TaskCompletionSource<int>();
operation.Aborted += (sender, args) => tcs.TrySetException(new SomeExecptionHere());
operation.Completed += (sender, args) => tcs.TrySetResult((int)operation.Result);
//The operation may have already finished and this check accounts for
//the race condition where neither of the events will ever be called
//because the events where raised before you subscribed.
var status = operation.Status;
if (status == DispatcherOperationStatus.Completed)
{
tcs.TrySetResult((int)operation.Result);
}
else if (status == DispatcherOperationStatus.Aborted)
{
tcs.TrySetException(new SomeExecptionHere());
}
return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4654 次 |
| 最近记录: |