英文:
Threads, Tasks, async and await, how do they actually work?
问题
I'm currently learning about C#, I'm wondering how Thread
, Task
, async
, and await
really work. This is what I understand:
Task.Run(MyTask)
is always executed on a new thread (in the thread pool).- Because of this,
Task
will run in parallel with the method that calls it (because they are on two different threads). - Therefore, use
await
to wait for the result of thatTask
, then continue executing the code below. - This is my example code:
static void Main(string[] args)
{
Task.Run(MyTask);
Console.WriteLine("Do main work...");
Thread.Sleep(5000);
}
static async Task MyTask()
{
await MyMiniTask();
Console.WriteLine("Do Task...");
}
static async Task MiniTask()
{
await Task.Delay(1000);
Console.WriteLine("Do Mini Task...");
}
output:
Do main work...
Do Mini Task...
Do Task...
As I understand it, the code should run like this:
- Run program -> Main thread is initialized to run the program.
Task.Run(MyTask)
-> thread A in the thread pool will handleMyTask
.- In the output, print out “Do main work…” first, even though the console WriteLine is written after
Task.Run(MyTask)
. The reason is because the Main thread and thread A are two different threads, so they will be executed in parallel. - Back to thread A and
MyTask
, it encounters the statement:await MiniTask
-> thread B in the thread pool will handleMiniTask
(a new thread will always be used to handleMiniTask
even if there is noawait
). - Because of using
await
,MyTask
will have to wait forMiniTask
to complete, and while waiting, thread A of MyTask does not handle anything -> MyTask will be marked as "a pause point" here and C# will release thread A back to the thread pool, thread A can now do another job. - When
MiniTask
is completed, C# will return to "the pause point" ofMyTask
, and handle it with another thread in theThreadPool
(it could be thread A or any other free thread).
=> The meaning of using async
await
is: it will wait for the result of the asynchronous task (MiniTask
), the await
keyword when used will release the thread of the method that calls it (Thread A of MyTask
), and ThreadPool
will allocate another thread to continue processing this method after MiniTask
has completed.
=> There is a difference between using the Wait()
method of Task
and the keyword await
, which is Wait()
will not release the thread of the method that calls it (I have tried).
=> Summary (according to my understanding):
- When you want to perform multiple tasks in parallel without affecting the main thread -> use
Thread
, and now more modern isTask
. - When you want to wait for the result of a
Task
->Wait()
it. - When you want to wait for the result of a
Task
, but want to release the Thread of the method that calls thatTask
in the waiting time ->await
it.
I don't know if I understand that right?
Sorry if my English is not good
This example code actually works and prints the output as above.
But I don't know if it works the way I think or just a coincidence.
英文:
I’m currently learning about C#, I’m wondering how Thread
, Task
, async
and await
really work. This is what I understand:
Task.Run(MyTask)
is always executed on a new thread (in the thread pool)- Because of this,
Task
will run in parallel with the method that calls it (because they are on two different threads) - Therefore, use await to wait for the result of that
Task
, then continue executing the code below. - This is my example code:
static void Main(string[] args)
{
Task.Run(MyTask);
Console.WriteLine("Do main work...");
Thread.Sleep(5000);
}
static async Task MyTask()
{
await MyMiniTask();
Console.WriteLine("Do Task...");
}
static async Task MiniTask()
{
await Task.Delay(1000);
Console.WriteLine("Do Mini Task...");
}
output:<br>
Do main work...<br>
Do Mini Task...<br>
Do Task...<br>
As I understand it, the code should run like this:
- Run program -> Main thread is initialized to run the program
Task.Run(MyTask)
-> thread A in the thread pool will handleMyTask
- In the output, print out “Do main work…” first, even though the console writeline is written after
Task.Run(MyTask)
. The reason is because Main thread and thread A are two different threads, so they will be executed in parallel - Back to thread A and
MyTask
, it encounters the statement: await MiniTask -> thread B in the thread pool will handleMiniTask
(a new thread will always be used to handleMiniTask
even if there is noawait
) - Because of using
await
,MyTask
will have to wait forMiniTask
to complete, and while waiting, thead A of MyTask does not handle anything -> MyTask will be marked as "a pause point" here and C# will release thread A back to the thread pool, thread A can now do another job - When
MiniTask
is completed, C# will return to "the pause point" ofMyTask
, and handle it with another thread in theThreadPool
(it could be thread A or any other free thread)
<br> => The meaning of using async await is: it will wait for the result of the asynchronous task (MiniTask
), await keyword when used will release the thread of the method that calls it (Thread A of MyTask
), and ThreadPool
will allocate another thread to continue processing this method after MiniTask has completed.
<br>There is a difference between using the Wait()
method of Task
and the keyword await
, which is Wait()
will not release the thread of the method that calls it (I have tried)
<br>
=>> Summary (according to my understanding):
- When you want to perform multiple tasks in parallel without affecting the main thread -> use
Thread
, and now more modern isTask
- When you want to wait for the result of a
Task
->Wait()
it - When you want to wait for the result of a
Task
, but want to release the Thread of the method that calls thatTask
in the waiting time ->await
it
<br>I don't know if I understand that right?
<br> Sorry if my English is not good
This example code actually works and prints the output as above.
But I don't know if it works the way I think or just a coincidence.
答案1
得分: 2
您的理解基本正确。需要纠正的一个点是:
Task.Run(MyTask)
总是在一个新线程上执行(在线程池中)
不是在一个新线程上。拥有一个ThreadPool
的整个目的是重用少量线程,以避免每次需要线程执行微小工作时都要付出创建新线程的代价。所以它只是一个线程,而不是一个新线程。
英文:
Your understanding is mostly OK. One point that needs to be corrected is here:
> Task.Run(MyTask)
is always executed on a new thread (in the thread pool)
Not on a new thread. The whole point of having a ThreadPool
is to reuse a small number of threads, in order to avoid paying the cost of creating a new thread each time a thread is needed to do some minuscule work. So it's just a thread, not a new thread.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论