2

I dont quite understand async/await benefit compare to threading.

In case inside a method, I have an operation without async/await version that consume some time like 20ms in the middle of other async operations.

Calling this method 1000 times, since async/await only execute inside one thread, it will comsume at least 20ms x 1000 time in my test (using Thread.Sleep to simulate).

Is there any misunderstanding about async/await?

public void Start()
{
    Task[] task = new Task[500];

    for (int i = 0; i < 500; i++)
    {
        task[i] = AsyncGet();
    }

    await Task.WhenAll(task);
}
public async Task<bool> AsyncGet()
{
    HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.example.com");
    req.Method = "GET";
    using(HttpWebResponse res = (HttpWebResponse)await req.GetResponseAsync())
    {

        Thread.Sleep(20);//Simulate an operation without async/await version that consume a little bit time

        using (Stream responseStream = res.GetResponseStream())
        {
             StreamReader sr = new StreamReader(responseStream, Encoding.ASCII);
             string resp = await sr.ReadToEndAsync();
        }
    }
}

Update question:

If I have a need to do some non-async/await operation like manipulating json after getting http response using external library. What is the best practice to avoid the time wasted?

Isolet Chan
  • 417
  • 6
  • 20
  • why only 1 thread , it uses any available threads in the thread pool. – eran otzap Sep 06 '14 at 10:26
  • You usually would try to avoid having non-async long lasting operations. Or in case the synchronization context doesn't matter you can use `ConfigureAwait(false)` on the returned `Task` object to let the continuation continue on any context. – Dirk Sep 06 '14 at 10:27
  • @eranotzap The code posted runs on 1 thread. `GetResponseAsync` might internally use another thread but given that's it's an IO operation it's far more likely they use something like an IO completion port. – Dirk Sep 06 '14 at 10:29
  • There was no code when i wrote my remark . – eran otzap Sep 06 '14 at 10:37
  • @Dirk look as Sriram's answer below . the callback could occur on multiple threads from the thread pool . – eran otzap Sep 06 '14 at 10:45

3 Answers3

4

No, not necessarily. If you're calling Start method from SynchronizationContext which is single threaded (Say any UI Context like WindowsFormsSynchronizationContext or DispatcherSynchronizationContext) answer is yes [*].

If you call Start from some other thread (say worker thread). It will not take 20ms x 1000. Because the code after await will be executed in ThreadPool thread in that case. So there can be N number of threads executing the code after await. Where N will be less than or equal to 500 in your case.

That said, you shouldn't block in async method. If at all you need to use any synchronous code inside an async method, you should use await Task.Run(()=> CodeThatBlocks())

* If SynchronizationContext is not overwritten by SynchronizationContext.SetSynchronizationContext

Community
  • 1
  • 1
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
2

Is there any misunderstanding about async/await?

Yes, you seem to have a misunderstanding. You can't simulate async-await behavior with Thread.Sleep which is a blocking call. When you await Task.WhenAll, multiple async requests execute concurrently, disregarding the underlying thread.

If you want to offload multiple requests concurrently, test them with await Task.Delay, you'll notice the change in behavior.

You can take this a step further and use ConfigureAwait(false) when calling GetResponseAsync so the continuation of your method wont marshal work back to the original SynchronizationContext (Which is important when dealing with custom ones such as WinFormSynchronizationContext) and continue execution on an IOCP.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
0

Sleeping a thread will still sleep the thread, regardless of any async / await structure. The idea with async / await is to keep each thread as occupied as possible to avoid having to create lots of threads just waiting for I/O. Performing CPU-intensive operations in the background will still require you to create threads.

In other words, the example you provide will cause the thread to freeze for 20 ms regardless as it is not the intended use case for async/await.

In other words, either:

  • Just use async I/O. Don't do any CPU-intensive processing (nor use Sleep).
  • Use a thread pool.
Krumelur
  • 31,081
  • 7
  • 77
  • 119