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).
source share