C# 等待任务中的等待任务-代码的其余部分何时执行?
考虑主窗体加载事件的这一部分:C# 等待任务中的等待任务-代码的其余部分何时执行?,c#,asynchronous,task,C#,Asynchronous,Task,考虑主窗体加载事件的这一部分: private async void MainForm_Load(object sender, EventArgs e) { var ServerConfigFile = new ClientConfigFile(Environment.CurrentDirectory); ServerConfigFile.GenerateConfigFile(); var taskCheck = Task.Run(() =&g
private async void MainForm_Load(object sender, EventArgs e)
{
var ServerConfigFile = new ClientConfigFile(Environment.CurrentDirectory);
ServerConfigFile.GenerateConfigFile();
var taskCheck = Task.Run(() => CheckUpdate());
await taskCheck;
lblUpdateMessage.Text = "Finished...";
//more code here
}
以及CheckUpdate
功能本身:
private async void CheckUpdate()
{
var connection = new ServerConnection(this);
Helper.CrossThreadInvoke(lblFileDownload, () => lblFileDownload.Text = "Downloading");
Helper.CrossThreadInvoke(lblFileDownload, () => lblFileDownload.Text = "Done");
var taskConfig = Task.Run(() => connection.GetServerConfig());
await taskConfig;
///some unrelated control changes here
}
此代码是否正确地等待CheckUpdate
完成其所有代码的运行(包括最后注释的控件更改)?我的推理是,它启动一个任务
,其中包含CheckUpdate
,然后等待
,将控制权返回到主窗体
CheckUpdate
运行一个任务,其中包含GetServerConfig
函数,等待
,将控制权传递回MainForm\u Load
,但由于它仍在等待CheckUpdate
完成,因此它不会继续执行lblUpdateMessage.Text=“Finished…”代码>行。还是我弄错了
Tl;dr在显示Finished
之前,此代码是否确实等待所有CheckUpdate
完成
在显示Finished之前,该代码是否实际等待所有CheckUpdate完成
否,因为CheckUpdate
是一种async void
方法
您可以将其设置为async Task
,它将正确地等待CheckUpdate
完成:
private async Task CheckUpdate()
但是,看看您的CheckUpdate
函数,它似乎不需要在后台线程上运行。它更新UI控件,在后台线程上运行一些东西,然后更新UI控件。它显然是UI层的一部分,正如Servy指出的那样,跳转到后台线程(在MainForm\u Load
中运行Task.Run
)只是跳回UI线程(Helper.CrossThreadInvoke
)
因此,删除这些不必要的线程跳转:
private async void MainForm_Load(object sender, EventArgs e)
{
var ServerConfigFile = new ClientConfigFile(Environment.CurrentDirectory);
ServerConfigFile.GenerateConfigFile();
await CheckUpdateAsync();
lblUpdateMessage.Text = "Finished...";
}
private async Task CheckUpdateAsync()
{
var connection = new ServerConnection(this);
lblFileDownload.Text = "Downloading";
lblFileDownload.Text = "Done";
await Task.Run(() => connection.GetServerConfig());
// some unrelated control changes here
}
最后,正如EJoshuaS所指出的,ServerConnection.GetServerConfig
听起来确实像是一个基于I/O的操作。您可以使这些调用自然异步(例如,使用HttpClient
),从而消除对任务的任何需要。运行:
private async Task CheckUpdateAsync()
{
var connection = new ServerConnection(this);
lblFileDownload.Text = "Downloading";
lblFileDownload.Text = "Done";
await connection.GetServerConfigAsync();
// some unrelated control changes here
}
有没有一个原因让你不能试着去看?为什么你在后台线程中运行一个方法只是为了让它安排在UI线程或其他后台线程中运行?只需在UI线程上运行它。@Janushoff是的,确实如此。该方法没有执行任何长时间运行的非UI工作,它只是执行UI工作并安排非UI工作在另一个线程中运行。不,假设它实际上是一个长时间运行的非UI操作,情况似乎就是这样。@Janushoff您的代码没有说它失败。它询问它是否会失败。如果你知道它失败了,那么显然你已经知道你问题的答案了。