我知道通常情况下在库代码中应该使用ConfigureAwait(false)
。除非我知道续体需要调用方上下文。
但是,如果我不知道是否需要调用方上下文,我该怎么办呢? 我猜在这种情况下不应该使用ConfigureAwait(false)
,但我想确认一下。
例如:我的类有几个事件:
public static event TriggeredWebhookInfo WebhookTriggered;
public static event ReadonlyWebhookInfo WebhookCancelled;
这里有一个方法(它是private
的,因为它被调用了一个返回public Task
的方法,但它也使用了ConfigureAwait(false)
):
private static async Task<HttpResponseMessage> TriggerTaskAsync(string url, WebhookBody body)
{
if (body == null || url == null)
{
WebhookCancelled?.Invoke(url, body);
Logger.Write(InternalTag.Sender, "Webhook cancelled: " + url, LogType.Normal);
return null;
}
HttpResponseMessage response = await Client.PostAsync(url, GetContent(body)).ConfigureAwait(false);
WebhookTriggered?.Invoke(url, body, response);
Logger.Write(InternalTag.Sender, "Webhook triggered: " + url, LogType.Normal);
return response;
}
当然,这对于任何终端应用程序完全可行。然而,如果事件在非终端应用程序中调用由用户分配的UI上下文上的方法会发生什么情况呢?Invoke()
会减轻任何问题吗?还是我应该从调用此方法的调用堆栈中删除ConfigureAwait(false)
?
when I know that continuation will need caller context.
that means, when your continuation needs to return to that context. Even if you know that the caller will want to return to its original context, let the caller decide. If in doubt, useConfigureAwait(false)
- Panagiotis Kanavosasync void
而不是async Task
。它们运行的线程应该被记录 - 是由控件/线程池/其他拥有的线程还是 UI 线程?您会发现事件文档说明事件是在此或那个事件上引发的。如果您希望它们在 UI 线程上运行,则可能需要采取额外的措施来查找 UI 同步上下文。除非TriggerTaskAsycn
是从 UI 线程本身调用的,否则简单地删除ConfigureAwait(false)
将无法做到这一点。 - Panagiotis Kanavos