[英]await inside a WPF Dispatcher call
在傳遞給調度程序的委托中確保錯誤處理的最佳解決方案是什么?
簡而言之:我需要在將計算解析為 Foo 后返回一個數字。 該計算非常緩慢,必須在 UI 線程上完成。 計算必須作為Task<string>
交給另一個類。
我能想出的唯一解決方案是 CallFooWithATask___3 - 甚至不確定..
public class Foo
{
public void CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(Task<string> task) { }
}
// CallFooWithATask___ is invoked from unknown thread. Can't wait for GetWithSideEffects on calling thread
public class SomeClass
{
private TextBox textBox;
public int CallFooWithATask___1(Foo foo)
{
// not good - async void -> no error handling
var tcs = new TaskCompletionSource<string>();
Dispatcher.CurrentDispatcher.BeginInvoke(async () =>
{
var a = await GetWithSideEffects();
textBox.Text = a;
tcs.SetResult(a);
});
// quite fast - probally put it in a queue and returns
foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(tcs.Task);
return 1;
}
public async Task<int> CallFooWithATask___2(Foo foo)
{
// not good - still async void -> no error handling .. when is foo actually called? I assume when hitting the inner await'ish?
var task = await Dispatcher.CurrentDispatcher.InvokeAsync(async () =>
{
var a = await GetWithSideEffects();
textBox.Text = a;
return a;
});
// quite fast - probally put it in a queue and returns
foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(task);
return 1;
}
public int CallFooWithATask___3(Foo foo)
{
// what is the elegant solution - probally not this?
var tcs = new TaskCompletionSource<string>();
Dispatcher.CurrentDispatcher.BeginInvoke(async () =>
{
try
{
var a = await GetWithSideEffects();
textBox.Text = a;
tcs.SetResult(a);
}
catch (Exception ex) { tcs.SetException(ex); }
});
// quite fast - probally put it in a queue and returns
foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(tcs.Task);
return 1;
}
// this might trigger ui updates and is very slow ..
private Task<string> GetWithSideEffects()=> Task.FromResult("42");
}
你很接近。 只需在方法或Func<Task<string>>
提取異步代碼,以避免以async void
結尾:
Func<Task<string>> func = async () =>
{
var a = await GetWithSideEffects();
return a;
};
然后使用InvokeAsync
調用它。 你最終會得到一個Task<Task<string>>
。 內部任務是異步方法返回的任務,外部任務是InvokeAsync
生成的InvokeAsync
用於指示實際調度調用的時間。 使用.Unwrap
合並這些任務,最后將它們發送到你的另一個方法:
var task = Dispatcher.InvokeAsync(func).Task.Unwrap();
foo.CallMeWithATaskThatIsFinishedWhenTheUIIsUpdated(task);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.