How to make ASP.Net MVC Controller Action Async

My desire is to create an Action MVC controller that performs lengthy I / O operations asynchronously. My goal is to avoid thread binding in the ASP.Net thread pool until this lengthy method completes.

The action calls two calls.

The first call is a third-party dll that does not contain asynchronous methods. This dll reads from a proprietary database and performs quite complex cpu-bound processing. This may take up to two seconds.

The second call uses the results of the first call as parameters that are passed to the database query using the Entity Framework.

Simplified, this action:

public async Task<ActionResult> MyActionAsync(arg1, arg2) { var parameters = 3rdPartyComponent.TakesLongTime(arg1, arg2); Task<List<MyClass>> genericList = null; using (DbContexts.MyDbContext db = new DbContexts.MyDbContext()) { genericList = await db.Database.SqlQuery<MyClass>(sql,parameters).ToListAsync(); } return View("MyView", genericList); } 

I would like to call 3rdPartyComponent on hold. My initial idea was to do this:

 var parameters = await Task.Run(() => 3rdPartyComponent.TakesLongTime()).ConfigurateAwait(false); 

but I read several subject experts who categorically state that using Task.Run () inside asp.net MVC Action is counterproductive and should never be executed.

3rdPartyComponent is a black box of compiled code, it cannot be changed to add async methods.

Is there a way to make the 3rdPartyComponent call expected so that the whole action is performed without thread binding in the asp.net thread pool?

+5
source share
2 answers

The first call is a third-party dll that does not contain asynchronous methods. This dll reads from a proprietary database and performs quite complex cpu-bound processing.

I would like to call 3rdPartyComponent on hold.

Is there a way to make the 3rdPartyComponent call expected so that the whole action is performed without thread binding in the asp.net thread pool?

The code is already as good as it can get. Neither Task.Run nor Task.Factory.StartNew will do you any good (even if you pass the LongRunning flag).

Since the dll-sided dll makes the code binding to the processor, it needs a thread. Even if you can change it, you can make asynchronous access to the database (I / O). The processor is synchronous in its own way, and from your description it looks like the processor works in most cases.

The whole point of avoiding Task.Run (and even worse Task.Factory.StartNew ) on ASP.NET is that they cause less efficient behavior. By freeing up the ASP.NET request stream, you simply return the stream to the thread pool until it is in use; there is nothing magical or special about ASP.NET request streams. Thus, Task.Run frees the thread thread thread thread by switching to another thread pool thread, and Task.Factory.StartNew using LongRunning frees the thread pool thread, creating a whole new thread, scheduling before, and then tearing this thread down at the end (this behavior is not documented or specified, but this is the current behavior).

So, what are you doing, unnecessary stream switches (and in the case of StartNew , the whole additional stream) StartNew . ASP.NET is designed to handle synchronous and asynchronous work; if you have synchronous code, it's best to just execute it directly, just like your code already does.

+6
source

Yes, I would argue that using Task.Run in the asynchronous server method is an anti-pattern, because the work you are planning will just be exacted in ThreadPool, and this is exactly the place you just came from ... NET gain zero (minus the overhead of scheduling a callback in ThreadPool).

My first thoughts are to cancel the job with

 Task.Factory.StartNew(action,TaskCreationOptions.LongRunning) 

TaskCreationOptions.LongRunning is a hint that the work should be performed in a new thread, not in ThreadPool.

... but if this is a heavy traffic method, you run the risk of creating threads faster than they are cleared, and now you have lost the benefits of ThreadPool management.

If the traffic is really as high as you say and requires this kind of special treatment, it could be something like throttling and / or caching ... But that would be another question ...

+1
source

Source: https://habr.com/ru/post/1233803/


All Articles