如何等待task.run

时间:2015-05-23 01:32:51

标签: c# .net windows-store-apps async-await task-parallel-library

我正在编写一个Windows应用商店应用,需要Task.Run方法的帮助。我正在调用服务从服务中检索数据;因为我想在互联网断开时取消任务我正在通过CancellationToken

await Task.Run(async () => await Download1(), cts.Token); 

还有另一个下载方法应该在上面的任务完成后运行,所以我使用await。这两个任务都写入相同的文件,因此我想确保它们不会并行运行。

await Task.Run(async () => await Download2(), cts.Token); 

问题是上面的任务2在任务1完成时启动,因此两个任务并行运行。我做错了什么?请指教。

Download1看起来像这样: -

 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();
                            });

            }
        }

2 个答案:

答案 0 :(得分:5)

您使用接受CoreDispatcher.RunAsyncDispatchedHandlerDispatchedHandler有这个签名:

public delegate void DispatchedHandler()

因此,当你传入async lambda时,它最终将成为async void。由于没有任何任务被返回,因此无法await。这意味着lambda中await之后的所有内容将同时在不同的线程上运行。

您不应该将async代表传递给该方法。

作为旁注,传递CancellationToken并不能自动停止操作。它只能在开始操作之前停止操作,或者如果您在操作中的某个位置观察令牌。

因此,要实际使用CancellationToken Download,请接受使用它,这会使Task.Run多余:

await Download1Async(cts.Token);

答案 1 :(得分:5)

你能按顺序打电话吗?

await Task.Run(async () =>
{
    await Download1();
    await Download2();
}); 

除非您从UI线程调用,否则您可能甚至不需要Task.Run。如果您已经在后台线程,请尝试:

await Download1();
await Download2();

当然,您的取消令牌可能应该以任何方式传递到下载功能。