0

Assume the following fictitious (and useless) methods:

public async Task SomethingAsync()
{
    await SomeAsyncOperation();
}

public async Task Execute(int numOfTimes)
 {
    var tasks = new List<Task>();

    for (var i = 0; i < numOfTimes; i++)
    {
        // how does this...
        var task = Task.Run(async () => await SomethingAsync());
        // differ to the line below? (i.e. no async/await in Task.Run)
        // var task = Task.Run(() => SomethingAsync());

        tasks.Add(task);
    }
    await Task.WhenAll(tasks);
}

public async Task Test()
{
    await Execute(10);
}

How does the presence or absence async/await keywords within Task.Run() affect the tasks in question?

I found a similar question on SO, which however .Resulted the task, something which I am not doing.

globetrotter
  • 997
  • 1
  • 16
  • 42
  • 1
    If you don't either asynchronously or synchronously wait on the code inside of `Task.Run` then the returned `Task` will complete before the inner code does. The difference between asynchronous waiting and synchronous waiting is just a matter of a thread being blocked during whatever is asynchronous (likely IO). Additionally `Task.Run` is only useful here if there is some CPU intensive code somewhere, otherwise just capturing the tasks from calling `SomethingAsync` would be good enough. – juharr May 16 '18 at 15:07
  • @Evk is that a duplicate? I'm explicitly asking about `async` and `await` within `Task.Run` – globetrotter May 16 '18 at 15:09
  • thanks @juharr, so you mean that `Task.Run(() => SomethingAsync());` would block, as opposed to `Task.Run(async () => await SomethingAsync());`? I don't understand how that could happen, as both are `Task`s nonetheless. – globetrotter May 16 '18 at 15:12
  • 1
    No `Task.Run(() => SomethingAsync())` will not block and the returned task will be completed almost immediately because it's not waiting on the `Task` from `SomethingAsync` to finish. The blocking version is `Task.Run(() => SomethingAsync().Result)`, but it blocks the thread that `Task.Run` uses, not the current thread. – juharr May 16 '18 at 15:14
  • And just doing `var task = SomethingAsync();` should be good enough unless you have CPU intensive code somewhere in `SomethingAsync` that you want to run in parallel. – juharr May 16 '18 at 15:17
  • Thanks, how does the presence of async/await keywords in `Task.Run` affect the `await Task.WhenAll(tasks)` part? – globetrotter May 16 '18 at 15:18
  • 1
    It basically means the `Task` returned by `Task.Run` will not complete until the `SomethingAsync` task completes. That means that `Task.WhenAll(tasks)` will return a `Task` that completes when all the `SomethingAsync` tasks complete. Without the `async/await` or `.Result` you end up with tasks that will complete before the `SomethingAscnc` tasks. And the `async/await` just means the threads used by `Task.Run` are not blocked during the asynchronous part of the code. – juharr May 16 '18 at 15:20
  • I consider this a duplicate, because you ask what's a difference between `Task.Run(() => return SomethingAsync())` and `Task.Run(async () => return await SomethingAsync())`, and so between `return SomeTask()` and `return await SomeTask()`, and that's exactly what duplicate is about. Of course code above won't compile, but just to clarify the point. – Evk May 16 '18 at 15:44

0 Answers0