xplat
xplat

Reputation: 8624

Proper approach on async/await method including Lambda

I would like to show two paradigms about async programming and listen to your comments.

A.

Let's say you have created a method like the following in a library to use it from your GUI clients.

public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
   TestObject testObj = new TestObject();
   ...fill in params to testObj...
   await MethodCallAsync(testObj);
   ....do other work synchronous.....
   ....continue fill testObj properties...
   await Task.Delay(1000) // just a delay for no reason
   ...continue synchronous work.....
   return testObj;
}

Ok, but this will chop my GUI context into small calling pieces, right? or I don't know if from the moment you declare a method async it will create a Task for all the operations inside?

If yes then great, no problem we can just declare it async and move on with our lives.

Lets say no and I would like to take the following approach so I won't disturb the GUI at all until my whole method call finishes and take the result so do something in my calling method.

B.

Another approach would be.

public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
   TestObject testObj = new TestObject()
   ..fill state params....
   return await Task.Factory.StartNew((state) =>
   {
      //But now I need to do async/await in here
      // is it a good practice to async await lambdas?
      // async/await practices say it's ok as long sas it is not becoming async void
      // which in our case is not.
      await MethodCallAsync(testObj);
       ....do other work synchronous.....
       ....continue fill state properties...
       await Task.Delay(1000) // just a delay for no reason
       ...continue synchronous work.....
       return state; // Our state and TestObject to examine after completion

   }, testObj);
}

Our problem now it's not only if we should asyncify the lambda, say you do it, it the will return a Task<Task<TestObject>> and definitely we don't want that.

You should call this up in the pipeline, most probably your GUI class.

private async void SomethingClickedOrTouched(object sender, EventArgs e)
{
   await RunThisAsyncToDoYourJob();
}

private async Task RunThisAsyncToDoYourJob()
{
   TestObject testObj = await myObject.DoSomeWork("param1", anotherObject);
}

It just bugs me a little and I really want into detail with async programming.

So, is A paradigm the correct approach anyway, and use the B paradigm only when the Task lambda inside code is completely synchronous? Thank you in advance.

Regards.

Upvotes: 1

Views: 413

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456587

The proper way to write an async method is to use ConfigureAwait(continueOnCapturedContext: false) whenever you don't need to resume on the captured context. This is normally done for all "library" code.

this will chop my GUI context into small calling pieces, right?

Yes (since you're not using ConfigureAwait).

or I don't know if from the moment you declare a method async it will create a Task for all the operations inside?

Yes, async will create a Task that represents the async method. However, the fact that there is a Task does not mean that its code is running on a background thread.

it the will return a Task<Task<TestObject>> and definitely we don't want that.

I'd like to know where everyone is getting the idea of using Task.Factory.StartNew for asynchronous tasks. Task.Run is superior if you want to run code on a background thread.


I have an async intro on my blog that you may find helpful.

Upvotes: 6

Related Questions