1

suppose sample snippet:

public async void writeDataOnFile (byte[] data, string filePath) {
   using(var fs = new FileStream(filePath)) {
      await File.WriteAsync(data,0,data.length);
   }
}

I know that no background thread is consumed from thread pool,but an IO operation will be started and thread will be notified at the end.

Question is: HOW does async/await understand that WriteAsync is an IO-bound method rather than a CPU-bound method?

Any help would be appreciated.

Dave
  • 2,829
  • 3
  • 17
  • 44
stefano m
  • 4,094
  • 5
  • 28
  • 27
  • 4
    The compiler doesn't need to understand that at all. It just schedules a continuation when the task returned by `File.WriteAsync` completes. *How* it completes is up to the implementation of `File.WriteAsync`. – Jon Skeet Nov 29 '17 at 23:04
  • For or more practical example on how tasks don’t care whether something is I/O or CPU bound maybe it helps if you take a look at https://msdn.microsoft.com/de-de/library/hh873178(v=vs.110).aspx#EAP where it shows a simple example how an event based action – download gets started and notifies when it’s finished – can be converted to a task. Something similar is done by WriteAsync where internally the OS notifies per callback when the operation finishes. – ckuri Nov 29 '17 at 23:20
  • 2
    Also, "no background thread is consumed from thread pool". I'm unsure about whether this statement is correct since I've never cared about the thread pool in particular, but I'm about 99% sure a background thread is *used*. I feel like you may be inferring incorrect information from that statement, whether it's technically correct or not. Not that `await` particularly cares about that either... – zzxyz Nov 29 '17 at 23:26
  • In my experience, it does tend to use a background thread, although you can limit the number of threads to 1 as I showed at https://stackoverflow.com/a/46892653/78162 if you're concerned about multiple threads encountering race conditions. – BlueMonkMN Nov 29 '17 at 23:32
  • The question posed in the title is slightly different the the question posed in the body. I believe others are answering based on the question in the body. For the question in the title, the answer involves understanding [I/O Completion Ports (IOCP)](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx), and how they relate to async/await. [Stephen Cleary has a blog about that](https://blog.stephencleary.com/2013/11/there-is-no-thread.html). – Matt Johnson-Pint Nov 29 '17 at 23:40

1 Answers1

3

Question is: HOW async/await understands that WriteAsync is an IO method rather than a CPU method?

The await keyword does not care whether it is IO or CPU bound. All it cares about is that the "call" is awaitable. Please see here for more details.

See this example below where the extension method returns a TaskAwaiter:

public static class ThisWorks
{
    public static System.Runtime.CompilerServices.TaskAwaiter GetAwaiter(this Int32 millisecondsDue)
    {
        return TimeSpan.FromMilliseconds(millisecondsDue).GetAwaiter();
    }

    private static System.Runtime.CompilerServices.TaskAwaiter GetAwaiter(this TimeSpan timeSpan)
    {
        return Task.Delay(timeSpan).GetAwaiter();
    }
}

Now to use that we can do this:

await 15;

There are better examples but at least this shows the point.

CodingYoshi
  • 25,467
  • 4
  • 62
  • 64