等待关键字阻止主线程 [英] await keyword blocks main thread
问题描述
所以我有以下代码
private async void button1_Click(object sender, EventArgs e)
{
await DoSomethingAsync();
MessageBox.Show("Test");
}
private async Task DoSomethingAsync()
{
for (int i = 0; i < 1000000000; i++)
{
int a = 5;
}; // simulate job
MessageBox.Show("DoSomethingAsync is done");
await DoSomething2Async();
}
private async Task DoSomething2Async()
{
for (int i = 0; i < 1000000000; i++)
{
int a = 5;
} // simulate job
MessageBox.Show("DoSomething2Async is done");
}
在显示两个MessageBox之前,主线程处于阻塞状态(我的意思是应用程序本身已冻结).我的代码显然有问题,我不知道是什么.我以前从未使用过async/await.这是我的第一次尝试.
Until both MessageBoxes are shown the main thread is block (I mean the application itself is frozen). There is obviously something wrong with my code and I can't figure out what. I've never used async/await before. this is my first attempt.
实际上,我要做的是异步启动DoSomethingAsync
的执行,这样,即使DoSomethingAsync不完整,单击按钮MessageBox.Show("Test");
也会执行.
Actually what i want to do is to start Execution of DoSomethingAsync
asynchronously so that when button is clicked the MessageBox.Show("Test");
would execute even though the DoSomethingAsync is incomplete.
推荐答案
我认为您误解了异步的含义. 这并不意味着该方法在另一个线程中运行!
I think you misunderstand what async means. It doesn't mean that the method runs in another thread!!
异步方法同步运行,直到第一个await
,然后将Task
返回给调用者(除非它是async void
,然后它什么也不返回).等待的任务完成后,通常在同一线程(如果具有SynchronizationContext
)上的await
之后恢复执行.
An async method runs synchonously until the first await
, then returns a Task
to the caller (unless it's async void
, then it returns nothing). When the task that is being awaited completes, execution resumes after the await
, usually on the same thread (if it has a SynchronizationContext
).
在您的情况下,Thread.Sleep
在第一次等待之前,因此它是同步执行的,然后将控制权返回给调用者.但是,即使它在await
之后,它仍然会阻塞UI线程,除非您特别配置了等待者不捕获同步上下文(使用ConfigureAwait(false)
).
In your case, the Thread.Sleep
is before the first await, so it's executed synchronously, before control is returned to the caller. But even if it was after the await
, it would still block the UI thread, unless you specifically configured the the awaiter not to capture the synchronization context (using ConfigureAwait(false)
).
Thread.Sleep
是一种阻止方法.如果您想要异步等效项,请按照Sriram Sakthivel的答案中的建议使用await Task.Delay(3000)
.它会立即返回,并在3秒后恢复,而不会阻塞UI线程.
Thread.Sleep
is a blocking method. If you want an async equivalent, use await Task.Delay(3000)
, as suggested in Sriram Sakthivel's answer. It will return immediately, and resume after 3 seconds, without blocking the UI thread.
一个常见的误解是异步与多线程有关.可以,但是在很多情况下不是.不会仅仅因为方法async
而隐式地产生一个新线程.为了产生新线程,必须在某个时候显式地完成它.如果您特别希望该方法在其他线程上运行,请使用Task.Run
.
It's a common misconception that async is related to multithreading. It can be, but in many cases it's not. A new thread is not implicitly spawned just because the method is async
; for a new thread to spawn, it has to be done explicitly at some point. If you specifically want the method to run on a different thread, use Task.Run
.
这篇关于等待关键字阻止主线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!