1

What's the difference between a synchronous void method using Task.Run compared to an asynchronous Task method simply awaiting? I'm torn between which one to use in a web application:

public void CreateScope<T>(Func<T, Task> serviceLayer) where T : class
    {
        Task.Run(async () =>
          {
              using (var scope = _serviceScopeFactory.CreateScope())
              {
                  var scopedService = scope.ServiceProvider.GetRequiredService<T>();
                  await serviceLayer(scopedService);
              }
          });
    }

or

public async Task CreateScopeAsync<T>(Func<T, Task> serviceLayer) where T : class
    {
        using (var scope = _serviceScopeFactory.CreateAsyncScope())
        {
            var scopedService = scope.ServiceProvider.GetRequiredService<T>();
            await serviceLayer(scopedService);
        }                
    }

I know Task.Run spins up a new thread but I have limited resources.

GH DevOps
  • 305
  • 1
  • 11
  • It's apples and oranges. One generates a Task running in the background, the other is an async method. A whole different thing. – JHBonarius Aug 05 '22 at 19:52
  • 1
    Also check other answers by [Stephen Cleary](https://stackoverflow.com/users/263693/stephen-cleary). He wrote great stuff about async programming – JHBonarius Aug 05 '22 at 19:55
  • @JHBonarius that may help but I need to explain a little more because I see the same information often and I may be ignorant in regards to the topic. I have to fire and forget to do my task in the background. So I'm calling Task.Run on a method without awaiting. Inside that method I'm calling my CreateScope function to resolve my dependencies. I was cautions about using the first method because it's calling Task.Run again. Should I call Task.Run only once? – GH DevOps Aug 05 '22 at 20:20
  • The right way to do that all depends on the exact details and context. Are you using asp.net? If yes, you could consider a background service. – JHBonarius Aug 05 '22 at 20:36
  • 1
    `I have to fire and forget` - in my experience, fire and forget is the wrong solution >95% of the time. [See my blog series](https://blog.stephencleary.com/2021/01/asynchronous-messaging-1-basic-distributed-architecture.html) for the correct solution. – Stephen Cleary Aug 05 '22 at 21:21
  • @StephenCleary that may be overkill for my situation – GH DevOps Aug 08 '22 at 12:34

2 Answers2

2

Task is not about threads and parallel execution, it is about asynchronous execution. So don't worry about your resources. You could also check this link - https://www.delftstack.com/howto/csharp/thread-vs-task-in-csharp/.

And difference between async Task and Task.Run - in order to call asynchronous method from the other method, that method should be async. But, sometimes you can not modify method signature. But, you need to call asynchronous method from it. How to do it? Spin up the task, using Task.Run syntax. It will do the same call, as you would call method as await ....

kosist
  • 2,868
  • 2
  • 17
  • 30
1

Task.Run uses the common ThreadPool to execute the task, and does not necessarily create a new thread each time.

Your first method is not marked as async and, as such, will spawn the task in the background and return instantly to the caller. The returned result (or thrown exception!) from inside the task will be ignored.

The second method on the other hand returns the created Task, allowing the caller to retrieve results and, most importantly, any exceptions that occur.

It's usually good practice to allow the caller to handle these tasks for you. So, if the framework or caller in question can adapt to call async methods, they're the better option. You can configure the thread pool to use on the framework or caller as appropriate.

henry700
  • 179
  • 3
  • 8