1

Lets say I have a method defined as follows:

public async Task CreateUser()
{
   await GetUserDetails();
   GetUserOrder();
}

private void GetUserDetails() {

private void GetUserOrder() {

Does the method GetUserDetails(); and GetUserOrder() have to be async as well to avoid UI blocking ?

I cannot await the GetUserDetails() method since it is not async. How can I achieve this in c# ? I want to ensure all these methods are invoked step by step.

ExpertGenie
  • 195
  • 3
  • 14
  • You really should never make a void method async unless its an event. You really need to provide more detail here, `async/await` is not some magic words that make everything faster, we need to know context – maccettura Dec 01 '17 at 17:37
  • `Task.Add` plus `Task.WaitAll`, you can see a reference here https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx – Hackerman Dec 01 '17 at 17:37
  • @maccettura : What if I make `private async Task GetUserDetails();` ? How can I ensure all my methods are invoked completely sequentially? – ExpertGenie Dec 01 '17 at 17:40
  • They don't have to be async, but if you want to await them then they should at least return a `Task`. Ultimately the idea is that somwhere in the call chain your code will `await` an IO bound async method that you don't want to block your thread. That or you have to spin up a thread for CPU bound code. – juharr Dec 01 '17 at 17:42
  • hi i provided you almost all the variation that you cant try as per your requirement ... – Pranay Rana Dec 01 '17 at 17:50
  • Does `GetUserOrder` ever take more than, say, 30ms to run synchronously? If not, don't worry about it. If yes, then yeah, that's going to block the UI thread for *more than 30ms*. – Eric Lippert Dec 01 '17 at 17:53
  • @EricLippert : Yeah it takes more than 30ms. How can I prevent this blocking of the UI thread ? What if I create another thread ? Seems legit ? – ExpertGenie Dec 01 '17 at 17:58
  • 2
    Is it taking more than 30ms because it is *doing a complicated computation that maxes out a CPU for more than 30ms*? If yes, then start a thread. Or is it taking so long because it is waiting for disk, network, or other I/O resource? If it is I/O bound then *do not start a thread*. Rewrite the method so that it uses asynchronous I/O ! – Eric Lippert Dec 01 '17 at 18:02
  • Its taking more than 30ms as it has to fetch data from the db, make a comparison then add to a list. – ExpertGenie Dec 01 '17 at 18:03
  • 2
    Then **under no circumstances should you start a thread**. Remember, doing a database lookup is, from the thread's perspective, like you need a recipe and so you order a cookbook from Amazon and wait a week for it to arrive. Here are your choices: (1) Order the cookbook and sit by your door doing nothing for a week until it arrives. (2) Hire a temp worker to sit by your door doing nothing for a week who then informs you when it arrives. Or (3) make a note to yourself to make dinner when the cookbook arrives, and keep living your life. Which do you choose? – Eric Lippert Dec 01 '17 at 18:06
  • (1) is what you're doing now -- synchronously waiting for the DB call to return. (2) is what you're suggesting: hiring an insanely expensive worker to do nothing but wait on your behalf. (3) is what you should do: **rewrite the method to use asynchronous database IO** and then **await the result**. – Eric Lippert Dec 01 '17 at 18:07
  • Nice example. I would choose (3). – ExpertGenie Dec 01 '17 at 18:08
  • `public Task async ObservableCollection MatchCustomers(ObservableCollection foundCustomers) { CustomersLoaded= new ObservableCollection(); foundTrucks = new ObservableCollection(); foundTrucks = await HandleTrucks(foundTrucks); TrucksLoaded = await ConstructTrucks(foundTrucks); await SavetoLocalDB(CustomersLoaded); return TrucksLoaded; }` Is this correct ? wait for each method to execute sequentially and completely? – ExpertGenie Dec 01 '17 at 18:14
  • Seems reasonable to me. Just remember that *await is an operator on tasks, not on calls*, and *await is the sequencing operation*, and you should be fine. – Eric Lippert Dec 01 '17 at 18:20
  • @EricLippert : Thanks man. I have been struggling a lot with these. The async/ await / Task thing is very confusing sometimes. So I should change the methods signature of all methods that I have awaited to `private async Task HandleTrucks` and so on. – ExpertGenie Dec 01 '17 at 18:22
  • You're welcome. The thing about async is that it tends to spread through a program; it's hard to make a program only a little bit asynchronous. The key is to identify the I/O bound operations that are the "leaves" of your blocking operations, asyncify them, and then move the asynchrony up the call chain until it's throughout the program. – Eric Lippert Dec 01 '17 at 18:24

3 Answers3

7

The relevant question is in a comment:

How can I ensure all my methods are invoked completely sequentially?

The fact that you're asking the question indicates that you don't understand what "await" is. Await is the sequencing operation on a asynchronous workflows. An await means this workflow will not proceed until the awaited task is complete. It's an asynchronous wait, hence the name await.

Consider this question: in a synchronous workflow, what is the sequencing operation?

No, really, give it some thought.

.

.

.

It is ;. When you say

fResult = foo();
bResult = bar();
qResult = qux();

that means that foo has to finish completely before bar can begin. That is not true for asynchronous workflows. If we have

fTask = fooAsync();
bTask = barAsync();
qTask = quxAsync();

Then the asynchronous operations can complete in any order. If we say

await fooAsync();
await barAsync();
await quxAsync();

Then barAsync will not start until fooAsync's task completes. await sequences the asynchronous workflow. The difference is that the thread can continue to do other unrelated work while asynchronously waiting for foo to complete, which is not true in a synchronous workflow; in a synchronous workflow the thread is already busy computing the foo result, so it can't do other work.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • My question is that I want the async method to be invoked completed in an orderly way. Its imperative that they complete in order. – ExpertGenie Dec 01 '17 at 18:06
1

yes if you want to wait than you have to write await for that methods also. because after first await your code agian will be synchronous ..and if UI thread than it will run on it.

1.you code will be , so by this code you code become asynchronous for GetUserORder also. you just have to wrap method in Task construct and return

public async Task CreateUser()
{
   await GetUserDetails();
   await Task.Factory.SartNew(()=> GetUserOrder());
}

2.or you can do this also

public async Task CreateUser()
{
   await  Task.Factory.SartNew(()=>{
           GetUserDetails();
           GetUserOrder(); });
}

3.or you can do like this also, in below code will not wait for getuserorder method and excute await one method

 public async Task CreateUser()
    {
       Task.Factory.SartNew(()=> GetUserOrder()).ContinueWith((t)=> Console.WriteLine("Completed");
       await GetUserDetails();
    }

4.or last one variation, here you start GetUserOrder first and dont wait for it than you call GetUserDetails in async fashion , and if you want to work on GetUserOrder method want to wait just use Wait method.

 public async Task CreateUser()
    {
      var task =  Task.Factory.SartNew(()=> GetUserOrder());
       await GetUserDetails();   
       if(!task.IsCompleted)
       task.Wait(); 
    }

in your case you can go for 3 and if you want to wait go for 4th one.


As you asked me in comment what is difference between Task.Run and statnew method -: for that you can check this SO question : Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew()

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
-1

You should put await only in front of async methods. To run a synchronous one that you don't want to wait, you can use a new thread from the tread pool:

new Thread(() => DoSomething()).Start();

or

Task.Factory.SartNew(()=> DoSomething());

Here is the help page: https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx

Otherwise, your call to GetUserDetails will have to finish before you execute the next line.

Miro J.
  • 4,270
  • 4
  • 28
  • 49