将异步结果返回给事件

3
假设我有一个API事件,在这个事件中我需要返回一个结果。我需要进行的计算使用了一个异步方法,该方法会创建一个控件(必须在UI线程上运行)。
private async void API_QueryControl(object sender, APIEventArgs e)
{
e.Result = await CreateControl();
}

private async Task<Control> CreateControl()
{
await Task.Delay(1000);
return new Panel();
}

显然这样做行不通,因为API_QueryControl在我设置结果之前就已经返回了。我无法控制API,这意味着事件无法改变。那么我该如何让事件等待结果呢?


2
你不需要这么做。你可以阻塞UI线程,更改或不使用该方法,找到更快的计算方式等。 - Servy
如何使用阻塞UI线程的方式使其正常工作?CreateControl().Result、CreateControl().Wait()等会导致死锁。 - user2533483
在这种情况下阻塞UI线程的一种方法是不使用async...;-) - C.B.
1个回答

0

您可以使用ConfigureAwait(false)来阻止当前(UI)线程,但避免死锁。像这样:

e.Result = await CreateControl().ConfigureAwait(false);

ConfigureAwait(false) 使得 CreateControl 中的 continuation 部分 - 即 await Task.Delay 后面的部分 - 在线程池上运行,而不是在原始的 UI 线程上运行。

我猜你使用异步方式的原因是有些特殊,而不是只写一个同步版本的 CreateControl。这不仅会是更简单的代码,而且还会使用原始(UI)线程来完成工作,而不是在 UI 线程等待时使用第二个线程。

此外,请注意,您应该始终防止从 async void 方法中抛出异常 - 可以参考这里的接受答案 here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接