这是我的实际代码:
async Task getData()
{
Thread.Sleep(5000);
Console.WriteLine("Step 1");
using (HttpClient api = new HttpClient())
await api.GetAsync("http://google.com/").ContinueWith(
(getTask) =>
Console.WriteLine(getTask.Result.StatusCode);
);
Console.WriteLine("Step 2");
}
private void button1_Click(object sender, EventArgs e)
{
Task<Task> task = new Task<Task>(getData);
task.Start();
task.Wait();
Console.WriteLine("Step 3");
}
我得到以下输出:
Step 1
Step 3
OK
Step 2
为什么Step 3
之后Step 2
不会出现?
如何让它按顺序工作,即仅在getData
中的所有内容都完成后返回getData
的来电者?
答案 0 :(得分:3)
您还应将事件处理程序标记为async
private async Task button1_Click(object sender, EventArgs e)
和await
代替Wait
:
private async Task button1_Click(object sender, EventArgs e)
{
await getData();
Console.WriteLine("Step 3");
}
当我们使用async / await模式时,我们应该采用这种方式,直到第一个方法启动它。否则,通过显式调用Wait
或Result
,我们可能会遇到死锁问题。此外,显式调用那些阻止执行线程的方法。所以你放弃使用async / await的主要好处,它不会阻塞正在执行的线程并在一个单独的线程上运行一些代码,一旦完成,就会从你停止的地方恢复执行代码。
答案 1 :(得分:2)
尝试简单明了地表达事物 - async Task
(和<T>
)方法本身负责分配代表其完成的Task
对象。
如果您发现自己使用async
方法和自行分配Task
个对象(可以直接在这里,也可以使用静态工厂方法,例如Task.Run
),您必须认识到现在存在多个Task
对象。您必须小心并认识到(在此处)创建Task
的情况,现在他们自己返回Task
。
如果可能的话,最好一直拥抱async
(当您将每个功能修改为async
时),您将倾向于找到每个呼叫网站并将该位置设为async
,并自行停止分配任何Task
。