如何等待 task.run
how to wait for task.run
我正在编写一个 windows 商店应用程序,需要一些关于 Task.Run
方法的帮助。我正在调用服务以从服务中检索数据;因为我想在互联网断开时取消任务我正在传递 CancellationToken
await Task.Run(async () => await Download1(), cts.Token);
完成上述任务后,还有另一种下载方法运行,所以我正在使用 await。这两个任务都写入相同的文件,所以我想确保它们不会 运行 并行。
await Task.Run(async () => await Download2(), cts.Token);
问题是上面的任务 2 在任务 1 未完成的情况下开始,因此两个任务 运行 是并行的。我做错了什么?请指教
下载 1 看起来像这样:-
public async Task Download1()
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
Status = "Downloading!";
var ListSetupTasks = new List<SetupView>();
foreach (var setup in AllSetupTasks.Setup)
{
ListSetupTasks.Add(new SetupViewModel(setup));
}
IEnumerable<Task> downloadTasksQuery = from setup in ListSetupTasks where setup.TaskType == TaskType.Web select _masterlistrepository.GetTask(setup, false, datetime, branch);
Task[] downloadTasks = downloadTasksQuery.ToArray();
await Task.WhenAll(downloadTasks);
IEnumerable<Task> FinalTasksQuery = from setup in ListSetupTasks where setup.TaskType == TaskType.Web select _masterlistrepository.GetTask(setup, false);
foreach (var task in FinalTasksQuery)
{
await task;
}
});
}
CancellationToken是这样使用的:-
async void NetworkChanged(object sender, NetworkConnectionStatusChangedEventArgs e)
{
if (e.Value == false && LoadingData == true)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
await _alertmessageservice.ShowAsync("", "Network error. Please retry!");
cts.Cancel();
});
}
}
你用的是CoreDispatcher.RunAsync
which accepts a DispatchedHandler
。 DispatchedHandler
有这个签名:
public delegate void DispatchedHandler()
所以当你传入一个 async
lambda 时,它最终会是 async void
。这使得无法 await
因为没有任务被返回。这意味着在你的 lambdas 中 await
之后的所有内容将同时在不同的线程上 运行。
您不应该将 async
委托传递给该方法。
作为旁注,传递 CancellationToken
不会启用自动停止操作。它只能在操作开始之前停止操作,或者如果您在操作内部某处观察到令牌。
所以,要实际使用 CancellationToken
Download
应该接受使用它,这使得 Task.Run
变得多余:
await Download1Async(cts.Token);
你能按顺序调用它们吗?
await Task.Run(async () =>
{
await Download1();
await Download2();
});
您甚至可能不需要 Task.Run
,除非您从 UI 线程调用。如果您已经在后台线程中,请尝试:
await Download1();
await Download2();
当然,您的取消令牌可能应该以任何一种方式传递到下载函数中。
我正在编写一个 windows 商店应用程序,需要一些关于 Task.Run
方法的帮助。我正在调用服务以从服务中检索数据;因为我想在互联网断开时取消任务我正在传递 CancellationToken
await Task.Run(async () => await Download1(), cts.Token);
完成上述任务后,还有另一种下载方法运行,所以我正在使用 await。这两个任务都写入相同的文件,所以我想确保它们不会 运行 并行。
await Task.Run(async () => await Download2(), cts.Token);
问题是上面的任务 2 在任务 1 未完成的情况下开始,因此两个任务 运行 是并行的。我做错了什么?请指教
下载 1 看起来像这样:-
public async Task Download1()
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
Status = "Downloading!";
var ListSetupTasks = new List<SetupView>();
foreach (var setup in AllSetupTasks.Setup)
{
ListSetupTasks.Add(new SetupViewModel(setup));
}
IEnumerable<Task> downloadTasksQuery = from setup in ListSetupTasks where setup.TaskType == TaskType.Web select _masterlistrepository.GetTask(setup, false, datetime, branch);
Task[] downloadTasks = downloadTasksQuery.ToArray();
await Task.WhenAll(downloadTasks);
IEnumerable<Task> FinalTasksQuery = from setup in ListSetupTasks where setup.TaskType == TaskType.Web select _masterlistrepository.GetTask(setup, false);
foreach (var task in FinalTasksQuery)
{
await task;
}
});
}
CancellationToken是这样使用的:-
async void NetworkChanged(object sender, NetworkConnectionStatusChangedEventArgs e)
{
if (e.Value == false && LoadingData == true)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
await _alertmessageservice.ShowAsync("", "Network error. Please retry!");
cts.Cancel();
});
}
}
你用的是CoreDispatcher.RunAsync
which accepts a DispatchedHandler
。 DispatchedHandler
有这个签名:
public delegate void DispatchedHandler()
所以当你传入一个 async
lambda 时,它最终会是 async void
。这使得无法 await
因为没有任务被返回。这意味着在你的 lambdas 中 await
之后的所有内容将同时在不同的线程上 运行。
您不应该将 async
委托传递给该方法。
作为旁注,传递 CancellationToken
不会启用自动停止操作。它只能在操作开始之前停止操作,或者如果您在操作内部某处观察到令牌。
所以,要实际使用 CancellationToken
Download
应该接受使用它,这使得 Task.Run
变得多余:
await Download1Async(cts.Token);
你能按顺序调用它们吗?
await Task.Run(async () =>
{
await Download1();
await Download2();
});
您甚至可能不需要 Task.Run
,除非您从 UI 线程调用。如果您已经在后台线程中,请尝试:
await Download1();
await Download2();
当然,您的取消令牌可能应该以任何一种方式传递到下载函数中。