【发布时间】:2020-07-28 16:04:29
【问题描述】:
我在下面的程序中打印了哪个线程执行每个调用的方法,结果很奇怪。我希望所有异步调用都由线程池线程执行,因为@Jon Skeet 提到异步调用使用 ThreadPool 线程并且线程池线程是后台线程。
线程 id 显示执行 Main 方法的同一线程执行所有调用的方法,但 DisplayResult 不是异步方法。
DisplayResult 的每个调用(不是异步方法)是如何由线程池线程执行的,而实际的异步方法在调用时是由非后台线程执行的,与执行主要方法?以及这个程序应该有多少个后台线程和非后台线程?
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]);
}
}
输出:
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
【问题讨论】:
-
"public static async Task Main()" 更像是在 Main 方法中启用 await 的语法糖,因此它的执行可能与您的预期不同(就像您观察到的代码一样)。
-
忽略
async。忽略任何关于线程的想法。阅读您的代码,就好像它是单线程的并且完全正常,直到您点击await并且已评估其右侧的任何内容以生成Task(包括在右侧输入任何方法调用)它)。恭喜,这正是发生的事情。在您第一次点击await之前,您在方法调用链中走了多远? -
I expected all asynchronous calls to be executed by a threadpool thread because @Jon Skeet mentioned that asynchronous calls use ThreadPool threads这绝对是错误的。我怀疑 Jon Skeet 实际上是这么说的,因为它不正确,但如果他这样做了,请链接到问题/答案,以便更正。这很简单,如果您不使用Task.Run()进行异步调用,那么您就没有使用线程池线程。一切都在一个线程上运行。当然,除非 async 方法不尊重 API 礼仪并调用Task.Run()或在实现中产生其他线程。 -
不要过分强调这一点,@MyWrathAcademia,但我建议您接近 cmets/answers,就好像您从未听说过有关 async/await 的任何信息,而不是主要考虑您理解它,但只需要澄清一些细节。这里有很多误解。
-
@MyWrathAcademia 因为 I/O 绑定代码存在固有的等待。当您的代码从文件请求字节时,它可以在等待时执行其他操作,例如尝试从另一个文件读取,即使没有第二个线程。这些来自Eric Lippert (an old article about C# 5.0 CTP, but still a good read) 和Steven Cleary 的文章是必读的。
标签: c# multithreading asynchronous async-await threadpool