【发布时间】:2020-02-27 04:21:18
【问题描述】:
在传递给调度程序的委托中等待时确保错误处理的最佳解决方案是什么?
简而言之:我需要在将计算解析为 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");
}
【问题讨论】:
-
你的问题是什么?
-
在传递给调度程序的委托中等待时确保错误处理的最佳解决方案是什么。
-
一般来说,我建议结构化代码以便 UI 调用逻辑,而不是逻辑调用 UI。 UI 不应该为逻辑提供服务。如果逻辑需要服务,则为其定义一个接口,然后 UI 可以实现该接口,如果绝对必要,使用
SynchronizationContext。
标签: c# wpf async-await