A way to create an asynchronous shell

What is the best way to create an asynchronous wrapper for a synchronous method?

// sync method public void LongOperation() { //code... } // versions of wrapper public async Task LongOpertionWrapperAsyncV1() { var task = Task.Factory.StartNew(LongOperation); await task.ConfigureAwait(false); } public Task LongOpertionWrapperAsyncV2() { var task = Task.Factory.StartNew(LongOperation); task.ConfigureAwait(false); return task; } 

Although the use of both versions is no different.

 async Task Executor() { await LongOpertionWrapperAsyncV1(); await LongOpertionWrapperAsyncV2(); } 

For methods that return a value (Task <T>), I use the first version.

But I would like to know your opinion.

And is there a general difference between these versions?

+5
source share
2 answers

You should use "something like" V2:

 public Task LongOpertionWrapperAsyncV2() { return Task.Run(LongOperation); } 

and

 async Task Executor() { await LongOpertionWrapperAsyncV2().ConfigureAwait(false); } 

This saves one context switch compared to V1. As long as you don’t need to “wait for another operation”, and async-Task is the last operation in the method, you can simply return the task and not wait for it and leave the wait to the caller (which may or may not add ConfigureAwait ).

Task.Factory.StartNew is only necessary if you want to set TaskCreationOptions.LongRunning , as suggested by HPT.

UPDATE:
As Stephen already had in mind: There are VERY few cases where you should do async over sync (but there are). So think about what you are doing before implementing something like this. It is simply said: if it is work with the CPU, DO NOT do it if it is some kind of “waiting for input-output” MAYBE. We have a case when we developed the "almost async all the way" library, which is designed to control various HW devices. There, the entire "shared library" is asynchronous, but some of the low-level device drivers and / or access libraries do not support async , so at the lowest level we do something like:

 public async Task<byte[]> ReadAsync(int length) { return Task.Run(() => hwDevice.Read(length)); } 

hwDevice.Read still blocks the thread, but not the central processor, so the user interface responds during the time that we expect I / O (in "real live" this is also some logic of cancellation and error handling).

+4
source

None of the solutions are correct . The best answer is not to expose asynchronous methods to synchronous code. I’ll talk more about the “why” on my blog .

If your code is asynchronous, use async and await . If this is not so, then no. This should be up to the caller, as they want to call the code (for example, using Task.Run ).

+14
source

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


All Articles