I printed which thread executes each called method in the following program and the results are very strange. I expected all asynchronous calls to be executed by a threadpool thread because @Jon Skeet mentioned that asynchronous calls use ThreadPool threads and that thread pool threads are background threads.
The thread id shows that the same thread that executes the Main method executes all called methods except for DisplayResult which is not an asynchronous method.
How is it that each call of DisplayResult, which is not an asynchronous method, is executed by a threadpool thread where as actual asynchronous methods when called are executed by a non-background thread, the same non-background thread that executed the Main method? And how many background threads and non-background threads should there be in this program?
public static async Task Main()
{
Console.WriteLine($"Main method: The thread executing this task is {Thread.CurrentThread.Name}, {Thread.CurrentThread.ManagedThreadId}");
if (Thread.CurrentThread.IsBackground)
{
Console.WriteLine($"And it is a background thread.");
}
else
{
Console.WriteLine("And it is a non-background thread");
}
Console.WriteLine();
if (Thread.CurrentThread.IsThreadPoolThread)
{
Console.WriteLine("It is a ThreadPoolThread");
}
else
{
Console.WriteLine("It is a non-ThreadPoolThread");
}
Task task1 = ProcessReadWriteAsync(@"/tmp/temp1Write.txt");
Task task2 = ProcessReadWriteAsync(@"/tmp/temp2Write.txt");
await task1;
await task2;
}
public static async Task ProcessReadWriteAsync(string filePath)
{
Console.WriteLine($"ProcessReadWriteAsync: The thread executing this task is {Thread.CurrentThread.Name}, {Thread.CurrentThread.ManagedThreadId}");
if (Thread.CurrentThread.IsBackground)
{
Console.WriteLine($"And it is a background thread.");
}
else
{
Console.WriteLine("And it is a non-background thread");
}
Console.WriteLine();
if (Thread.CurrentThread.IsThreadPoolThread)
{
Console.WriteLine("It is a ThreadPoolThread");
}
else
{
Console.WriteLine("It is a non-ThreadPoolThread");
}
try
{
await ReadWriteAsync(filePath);
} catch (Exception ex)
{
Console.WriteLine(ex.Message);
} finally
{
Console.WriteLine();
}
}
public static async Task ReadWriteAsync(string path, string text)
{
Console.WriteLine($"ReadWriteAsync 2 parameters: The thread executing this task is {Thread.CurrentThread.Name}, {Thread.CurrentThread.ManagedThreadId}");
if (Thread.CurrentThread.IsBackground)
{
Console.WriteLine($"And it is a background thread.");
}
else
{
Console.WriteLine("And it is a non-background thread");
}
Console.WriteLine();
if (Thread.CurrentThread.IsThreadPoolThread)
{
Console.WriteLine("It is a ThreadPoolThread");
}
else
{
Console.WriteLine("It is a non-ThreadPoolThread");
}
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, useAsync: true);
byte[] buffer = new byte[0x1000];
int noOfCharactersRead = await stream.ReadAsync(buffer, 0, buffer.Length);
DisplayResult(buffer: buffer);
}
public static async Task ReadWriteAsync(string path)
{
Console.WriteLine($"ReadWriteAsync 1 parameters: The thread executing this task is {Thread.CurrentThread.Name}, {Thread.CurrentThread.ManagedThreadId}");
if (Thread.CurrentThread.IsBackground)
{
Console.WriteLine($"And it is a background thread.");
}
else
{
Console.WriteLine("And it is a non-background thread");
}
Console.WriteLine();
if (Thread.CurrentThread.IsThreadPoolThread)
{
Console.WriteLine("It is a ThreadPoolThread");
}
else
{
Console.WriteLine("It is a non-ThreadPoolThread");
}
await ReadWriteAsync(path, "");
}
private static void DisplayResult(byte[] buffer)
{
Console.WriteLine($"DisplayResult: The thread executing this method is {Thread.CurrentThread.Name}, {Thread.CurrentThread.ManagedThreadId}");
if (Thread.CurrentThread.IsBackground)
{
Console.WriteLine($"And it is a background thread.");
}
else
{
Console.WriteLine("And it is a non-background thread");
}
Console.WriteLine();
if (Thread.CurrentThread.IsThreadPoolThread)
{
Console.WriteLine("It is a ThreadPoolThread");
}
else
{
Console.WriteLine("It is a non-ThreadPoolThread");
}
string DecodedText = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
string[] strings = DecodedText.Split('\n');
for (int index = 0; index < strings.Length;index++)
{
Console.WriteLine(strings[index]);
}
}
Output:
Main method: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
ProcessReadWriteAsync: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
ReadWriteAsync 1 parameters: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
ReadWriteAsync 2 parameters: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
ProcessReadWriteAsync: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
ReadWriteAsync 1 parameters: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
ReadWriteAsync 2 parameters: The thread executing this task is , 1
And it is a non-background thread
It is a non-ThreadPoolThread
DisplayResult: The thread executing this method is , 4
And it is a background thread.
It is a ThreadPoolThread
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
9. msdn.microsoft.com/library/hh191443.aspx 83732
10. msdn.microsoft.com/library/aa578028.aspx 205273
11. msdn.microsoft.com/library/jj155761.aspx 29019
12. msdn.microsoft.com/library/hh290140.aspx 117152
13. msdn.microsoft.com/library/hh524395.aspx 68959
14. msdn.microsoft.com/library/ms404677.aspx 197325
15. msdn.microsoft.com 42972
16. msdn.microsoft.com/library/ff730837.aspx 146159
17. msdn.microsoft.com/library/hh191443.aspx 83732
18. msdn.microsoft.com/library/aa578028.aspx 205273
19. msdn.microsoft.com/library/jj155761.aspx 29019
20. msdn.microsoft.com/library/hh290140.aspx 117152
21. msdn.microsoft.com/library/hh524395.aspx 68959
22. msdn.microsoft.com/library/ms404677.aspx 197325
23. msdn.microsoft.com 42972
24. msdn.microsoft.com/library/ff730837.aspx 146159
25. msdn.microsoft.com/library/hh191443.aspx 83732
26. msdn.microsoft.com/library/aa578028.aspx 205273
27. msdn.microsoft.com/library/jj155761.aspx 29019
28. msdn.microsoft.com/library/hh290140.aspx 117152
29. msdn.microsoft.com/library/hh524395.aspx 68959
30. msdn.microsoft.com/library/ms404677.aspx 197325
31. msdn.microsoft.com 42972
32. msdn.microsoft.com/library/ff730837.aspx 146159
33. msdn.microsoft.com/library/hh191443.aspx 83732
34. msdn.microsoft.com/library/aa578028.aspx 205273
35. msdn.microsoft.com/library/jj155761.aspx 29019
36. msdn.microsoft.com/library/hh290140.aspx 117152
37. msdn.microsoft.com/library/hh524395.aspx 68959
38. msdn.microsoft.com/library/ms404677.aspx 197325
39. msdn.microsoft.com 42972
40. msdn.microsoft.com/library/ff730837.aspx 146159
41. msdn.microsoft.com/library/hh191443.aspx 83732
42. msdn.microsoft.com/library/aa578028.aspx 205273
43. msdn.microsoft.com/library/jj155761.aspx 29019
44. msdn.microsoft.com/library/hh290140.aspx 117152
45. msdn.microsoft.com/library/hh524395.aspx 68959
46. msdn.microsoft.com/library/ms404677.aspx 197325
47. msdn.microsoft.com 42972
48. msdn.microsoft.com/library/ff730837.aspx 146159
49. msdn.microsoft.com/library/hh191443.aspx 83732
50. msdn.microsoft.com/library/aa578028.aspx 205273
51. msdn.microsoft.com/library/jj155761.aspx 29019
52. msdn.microsoft.com/library/hh290140.aspx 117152
53. msdn.microsoft.com/library/hh524395.aspx 68959
54. msdn.microsoft.com/library/ms404677.aspx 197325
55. msdn.microsoft.com 42972
56. msdn.microsoft.com/library/ff730837.aspx 146159
57. msdn.microsoft.com/library/hh191443.aspx 83732
58. msdn.microsoft.com/library/aa578028.aspx 205273
59. msdn.microsoft.com/library/jj155761.aspx 29019
60. msdn.microsoft.com/library/hh290140.aspx 117152
61. msdn.microsoft.com/library/hh524395.aspx 68959
62. msdn.microsoft.com/library/ms404677.aspx 197325
63. msdn.microsoft.c
DisplayResult: The thread executing this method is , 5
And it is a background thread.
It is a ThreadPoolThread
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
9. msdn.microsoft.com/library/hh191443.aspx 83732
10. msdn.microsoft.com/library/aa578028.aspx 205273
11. msdn.microsoft.com/library/jj155761.aspx 29019
12. msdn.microsoft.com/library/hh290140.aspx 117152
13. msdn.microsoft.com/library/hh524395.aspx 68959
14. msdn.microsoft.com/library/ms404677.aspx 197325
15. msdn.microsoft.com 42972
16. msdn.microsoft.com/library/ff730837.aspx 146159
17. msdn.microsoft.com/library/hh191443.aspx 83732
18. msdn.microsoft.com/library/aa578028.aspx 205273
19. msdn.microsoft.com/library/jj155761.aspx 29019
20. msdn.microsoft.com/library/hh290140.aspx 117152
21. msdn.microsoft.com/library/hh524395.aspx 68959
22. msdn.microsoft.com/library/ms404677.aspx 197325
23. msdn.microsoft.com 42972
24. msdn.microsoft.com/library/ff730837.aspx 146159
25. msdn.microsoft.com/library/hh191443.aspx 83732
26. msdn.microsoft.com/library/aa578028.aspx 205273
27. msdn.microsoft.com/library/jj155761.aspx 29019
28. msdn.microsoft.com/library/hh290140.aspx 117152
29. msdn.microsoft.com/library/hh524395.aspx 68959
30. msdn.microsoft.com/library/ms404677.aspx 197325
31. msdn.microsoft.com 42972
32. msdn.microsoft.com/library/ff730837.aspx 146159
33. msdn.microsoft.com/library/hh191443.aspx 83732
34. msdn.microsoft.com/library/aa578028.aspx 205273
35. msdn.microsoft.com/library/jj155761.aspx 29019
36. msdn.microsoft.com/library/hh290140.aspx 117152
37. msdn.microsoft.com/library/hh524395.aspx 68959
38. msdn.microsoft.com/library/ms404677.aspx 197325
39. msdn.microsoft.com 42972
40. msdn.microsoft.com/library/ff730837.aspx 146159
41. msdn.microsoft.com/library/hh191443.aspx 83732
42. msdn.microsoft.com/library/aa578028.aspx 205273
43. msdn.microsoft.com/library/jj155761.aspx 29019
44. msdn.microsoft.com/library/hh290140.aspx 117152
45. msdn.microsoft.com/library/hh524395.aspx 68959
46. msdn.microsoft.com/library/ms404677.aspx 197325
47. msdn.microsoft.com 42972
48. msdn.microsoft.com/library/ff730837.aspx 146159
49. msdn.microsoft.com/library/hh191443.aspx 83732
50. msdn.microsoft.com/library/aa578028.aspx 205273
51. msdn.microsoft.com/library/jj155761.aspx 29019
52. msdn.microsoft.com/library/hh290140.aspx 117152
53. msdn.microsoft.com/library/hh524395.aspx 68959
54. msdn.microsoft.com/library/ms404677.aspx 197325
55. msdn.microsoft.com 42972
56. msdn.microsoft.com/library/ff730837.aspx 146159
57. msdn.microsoft.com/library/hh191443.aspx 83732
58. msdn.microsoft.com/library/aa578028.aspx 205273
59. msdn.microsoft.com/library/jj155761.aspx 29019
60. msdn.microsoft.com/library/hh290140.aspx 117152
61. msdn.microsoft.com/library/hh524395.aspx 68959
62. msdn.microsoft.com/library/ms404677.aspx 197325
63. msdn.microsoft.c
async
. Ignore any thoughts about threads. Read your code as if it's single-threaded and entirely normal, right up until you hit anawait
and whatever is to the right of that has been evaluated to produce aTask
(that includes entering any method calls to the right of it). Congratulations, that's exactly what happens. How far do you get in your chain of method calls before you hit that firstawait
? – Damien_The_UnbelieverI expected all asynchronous calls to be executed by a threadpool thread because @Jon Skeet mentioned that asynchronous calls use ThreadPool threads
this is absolutely false. I doubt Jon Skeet actually said this because it is not correct, but if he did, please link to the question/answer so it can be corrected. It's very simple, if you're not usingTask.Run()
with asynchronous calls, you're not using threadpool threads. Everything is running on one thread. Unless of course, the async method doesn't respect API etiquette and callsTask.Run()
or spawns other threads in the implementation. – Patrick Tucci