我是否可以将JoinableTaskFactory与AspNetCore一起使用?

Jod*_*ell 5 c# async-await asp.net-core

我已经将Microsoft.VisualStudio.Threading导入.Net Core Web App。我专门这样做是为了利用AsyncLazy<T>

我想确保自己做对了,所以我导入了适当的分析器

警告和文档明确指出JoinableTaskFactory应将a 注入到我的实现中。

我的问题是,如何JoinableTaskFactory在.Net Core Web App的配置中实例化它?

简单吗

public void ConfigureServices(IServiceCollection services)
{
    // ...
        services.AddSingleton(new JoinableTaskFactory());
    // ...
}
Run Code Online (Sandbox Code Playgroud)

还是,这都是错误的吗?

And*_*ott 5

是的,您可以Microsoft.VisualStudio.Threading在 ASP.NET Core 应用程序中使用该库。但是虽然JoinableTaskFactory在这样的应用程序中“工作”,但这是一个很好的迹象,你做错了什么。

该分析仪总是合适的,当然,并警告你看到的是也许是指出你不应该叫Task.ResultTask.Wait()等,这些同步块线程,可严重降低你的web应用程序的可扩展性(或与此有关的任何应用程序)。您应该尽可能使用await代替。

JoinableTaskFactory当您无法使用await但您仍然需要调用异步代码时,是否可以介入。UsingJTF.Run仍然会阻塞调用线程,但它会以一种避免死锁的方式SynchronizationContext在应用程序中有单线程时这样做。我不认为ASP.NET Core 有这样的东西,所以这不是问题。JTF.Run仍然比Task.Wait因为它可以将原始线程重用于延续而不是第二个线程更有效。

如果您确实选择在 Web 应用程序中使用 JTF,并且 ASP.NET Core 不使用单线程,SynchronizationContext那么您可以创建单个 JTF 实例并将其与整个应用程序共享。但是,如果它确实有一个单线程SynchronizationContext,那么每个 Web 请求将是一个,这意味着您需要JoinableTaskContext每个请求创建一个新的,因为它们关联到一个SynchronizationContext。您总是从JoinableTaskContext实例中获取 JTF实例。


ziv*_*kan 1

vs-threading 文档的这一页

ThreadHelper.JoinableTaskFactory 属性仅适用于在 VS 进程中运行的代码。如果您的代码在 proc 之外运行(例如在 vstest.executionengine.exe 运行程序中),它将无法工作。

因此,正如包的名称Microsoft.VisualStudio.Threading所示,它旨在用于 Visual Studio 扩展。您为其 AsyncLazy 实现链接的代码使用 JoinableTaskFactory,因此它可能不适合 Visual Studio 之外的环境。我当然不会在需要切换到 UI 线程的 VS 扩展之外使用它。

Steven Cleary 的 AsyncEx 库有一个AsyncLazy,并且wiki 页面链接到这篇标题为 AsyncLazy 的 Steven Toub 博客文章。该博客文章指出,惰性语义并没有真正比所Task<T>提供的内容添加太多内容,尽管由于值工厂在到达等待之前可能会做很多工作,因此他的示例在线程池上运行它并解开Task<Task<T>>.

编辑:正如评论中所指出的,我从文档中引用的内容有些断章取义。然而,vs-threading 库是为了避免在同步上下文(主要是 GUI)中使用 async 时出现死锁。问题的作者正在使用的 ASP.NET Core 没有同步上下文,因此不需要专门担心主线程的死锁。虽然使用 vs-threading 库可能不会引起问题,正如我的引文所说,但我仍然认为它不适合没有同步上下文的任何东西,并且有更好的替代方案,例如Task<T>直接使用而不需要任何 AsyncLazy执行。