0

I want to have an async method in my call that would be called by my library consumers with an await. But the internal working of my method, while I need it to run on a separate thread, does not call any other await on it's own.

I just do the work the method is supposed to do and return the type. And the compiler warns me that this method will not run in an async way.

public async Task<MyResultObject> DoSomeWork()
{
     MyResultObject result = new MyResultObject();
     // Some work to be done here

     return result;
}

On the other hand, if I write a method that starts a new task using TaskFactory like this:

public Task<MyResultObject> DoSomeWork()
{
     return Task<MyResultObject>.Factory.StartNew(() =>
     {
         MyResultObject result = new MyResultObject();
         // Some work to be done here

         return result;
     });
}

Then I cannot call it using the await keyword like this await DoSomeWork().

How do I write an async (must be async and not task with result or wait) without using some await call inside?

developer82
  • 13,237
  • 21
  • 88
  • 153
  • 5
    `while I need it to run on a separate thread` - if you are not making that happen yourself inside the method, e.g. with `Task.Run()`, then that is not going to happen when your method is called with `await` either, because [`async` is not about threads](https://stackoverflow.com/q/17661428/11683). – GSerg Jan 03 '19 at 12:45
  • So what is it about? And how do I write it in an async/await way? – developer82 Jan 03 '19 at 12:46
  • 8
    `aync/await` is an implementation detail of the method. The only thing that matters is it returns a Task. If you need to return a task but have no async source just use `Task.FromResult` – Titian Cernicova-Dragomir Jan 03 '19 at 12:47
  • So all my code is running and written regularly and just returns a `Task.FromResult`? It doesn't make the code in sync and therefor blocking? – developer82 Jan 03 '19 at 12:49
  • 2
    Your code will be synchronous and will block. If you don't want that to happen, use `Task.Run`. – GSerg Jan 03 '19 at 12:51
  • 4
    If your method is *essentially synchronous*, leave it as a synchronous method and leave it up to your *callers* to decide whether to call it directly or to use e.g. `Task.Run`. As others have said (and as the compiler warnings say if you try to do this), `async` by itself *doesn't do anything* from the callers perspective. – Damien_The_Unbeliever Jan 03 '19 at 12:53
  • @InBetween You [RC](https://stackoverflow.com/a/9225932/11683). – GSerg Jan 03 '19 at 13:01
  • 2
    Async is about scaling, not multi-processing. Async methods generate code to give up their thread while they wait for some IO bound task (so the thread can be used to process other requests). Then, when the IO is completed, it resumes. – Erik Funkenbusch Jan 03 '19 at 13:04
  • `async` won't make anything run asynchronously by magic. It's syntactic sugar that allows you to use `await` to await *already* asynchronous operations without blocking. If your method has no `await` it will run synchronously – Panagiotis Kanavos Jan 04 '19 at 12:49
  • "Then I cannot call it using the await keyword like this await DoSomeWork()." What error do you get when you write that code? Why doesn't it work? – Servy Jan 04 '19 at 15:04

1 Answers1

1

You can do this

public Task<MyResultObject> DoSomeWork()
{
     MyResultObject result = new MyResultObject();
     // Some work to be done here

     return Task.FromResult(result);
}

which is exactly the same as

public async Task<MyResultObject> DoSomeWork()
{
     MyResultObject result = new MyResultObject();
     // Some work to be done here

     return result;
}

Only this version gives a warning and has slightly more overhead.

But neither will run on another thread. The only benefit is that they have an awaitable interface.

To do it in parallel, your code is Ok but Task.Run is preferred over StartNew():

public Task<MyResultObject> DoSomeWork()
{
     return Task.Run(() =>
     {
         MyResultObject result = new MyResultObject();
         // Some work to be done here

         return result;
     });
}

And in all these cases you can definitely await DoSomeWork()

bommelding
  • 2,969
  • 9
  • 14