Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I use a JoinableTaskFactory with AspNetCore?

I've imported Microsoft.VisualStudio.Threading into .Net Core Web App. I did this specifically to make use of AsyncLazy<T>.

I wanted to make sure I did this right, so I imported the appropriate Analyzers.

The warnings and the documentation clearly state that a JoinableTaskFactory should be injected into my implementation.

My question is, how should I instantiate that JoinableTaskFactory in the configuration of my .Net Core Web App?

Is it as simple as

public void ConfigureServices(IServiceCollection services)
{
    // ...
        services.AddSingleton(new JoinableTaskFactory());
    // ...
}

or, is that all wrong?

like image 521
Jodrell Avatar asked Apr 05 '19 12:04

Jodrell


1 Answers

Yes, you can use the Microsoft.VisualStudio.Threading library in ASP.NET Core applications. But while JoinableTaskFactory would "work" in such an app, it's a pretty good sign you're doing something wrong.

The analyzers are always appropriate of course, and the warnings you saw were perhaps pointing out that you shouldn't call Task.Result, Task.Wait(), etc. These synchronously block threads and can severely reduce the scalability of your web app (or any app for that matter). You should use await instead wherever possible.

JoinableTaskFactory is there to step in when you can't use await but you still need to call async code. Using JTF.Run will still block the calling thread, but it will do so in a way that avoids deadlocks when you have a single threaded SynchronizationContext in the application. I don't think ASP.NET Core has such a thing, so that's not a concern. JTF.Run is still more efficient than Task.Wait since it can reuse the original thread for continuations instead of a second thread.

If you do choose to use JTF in your web app, if ASP.NET Core doesn't use a single-threaded SynchronizationContext then you can create and share a single JTF instance with the entire app. But if it does have a single-threaded SynchronizationContext, it will be one per web request, which means you need to create a new JoinableTaskContext for each request since these are affinitized to one SynchronizationContext. You always get your JTF instance from a JoinableTaskContext instance.

like image 64
Andrew Arnott Avatar answered Sep 18 '22 23:09

Andrew Arnott