【问题标题】:Task-Like and ConfigureAwait(false), is it possible?Task-Like 和 ConfigureAwait(false),有可能吗?
【发布时间】:2020-07-18 16:28:43
【问题描述】:

我一直在阅读有关类似任务和等待类型的文章。我想我已经很好地掌握了它的基本机制(awaiter、asyncmethodbuilder ......),但是当我尝试理解 ConfigureAwait(false) 在这种情况下的用法时(如果这甚至可能的话)有些不对劲。

我的问题是:

ConfigureAwait 是否为“真正的”任务保留,意味着 SynchronizationContext 的使用与否?

如果是这样,并且假设您正在编写一个通用库,该库公开了它自己的类似任务类型的实现,您是否应该在代码遇到任务时只使用 ConfigureAwait(false)?

谢谢。

【问题讨论】:

  • 我的问题:为什么?你有什么具体的用例需要使用基于任务的异步编程,但不能使用内置的任务类?
  • 您知识渊博的答案是否取决于原因?问题是这是否可能。在我对此事的调查中,我没有找到答案。
  • Is ConfigureAwait reserved for "true" Tasks - 不,不是。请参阅devblogs.microsoft.com/dotnet/configureawait-faq,“ConfigureAwait(false) 做什么?”部分。
  • 是的,任何类型的任务都是可能的......但你必须写它。请参阅此 Marc 砾石库。特别寻找ConfiguredYieldAwaitable,这是一种配置Task.Yield 的方法,它有一个自定义的等待者。 mgravell.github.io/PooledAwait
  • 还有一些关于这个问题的答案的自定义配置的可等待对象的例子stackoverflow.com/q/51375326/491907

标签: c# async-await task-parallel-library synchronizationcontext configureawait


【解决方案1】:

如果您的库的任务类类型在等待时未捕获上下文,那么您的库的用户将无法执行此操作:

private async void Button_Click(object sender, EventArgs e)
{
    string input = Textbox1.Text;
    TaskLike<string> taskLike = YourLibrary.ProcessAsync(input);
    string result = await taskLike;
    Label1.Text = result // InvalidOperationException: Cross-thread operation not valid
}

另一方面,如果您的库的任务类类型总是在等待时捕获同步上下文,那么您的库作为其他库的构建块将效率低下,并且需要其他库作者jump through hoops为了以无同步上下文的方式调用您的库。因此,让您的任务类类型可配置以捕获同步上下文应该是一个理想的功能。

关于当你的库的内部代码遇到标准Tasks 时是否应该使用ConfigureAwait(false),这取决于你的库是否接受调用者提供的 lambdas。例如,如果您的库包含这样的方法:

public TaskLike<string> ProcessAsync(Action action);

...然后在内部等待 ConfigureAwait(false) 之后调用 action 可能会导致跨线程冲突异常,如果调用者的 lambda 包含线程仿射代码,例如读取 UI 控件的属性。为了解决这个问题,可能需要在方法的签名中引入一个配置参数continueOnCapturedContext。至少这是Polly library选择的解决方案。

【讨论】:

    猜你喜欢
    • 2014-06-25
    • 2020-07-27
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2013-02-01
    • 1970-01-01
    相关资源
    最近更新 更多