I am writing a windows store app and needs some help on Task.Run
method. I am calling service to retrieve data from a service; because I want to cancel the task when internet is disconnected I am passing CancellationToken
await Task.Run(async () => await Download1(), cts.Token);
There is another download method which should run after this above task is finished so I am using await. Both the tasks write to same files so I want to make sure that they do not run in parallel.
await Task.Run(async () => await Download2(), cts.Token);
The issue is that above task 2 starts without task 1 is finished and so both task run in parallel. What I am doing wrong? Please advise.
Download1 looks like this:-
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;
}
});
}
The CancellationToken is used like this:-
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();
});
}
}
You use the CoreDispatcher.RunAsync
which accepts a DispatchedHandler
. DispatchedHandler
has this signature:
public delegate void DispatchedHandler()
So when you pass in an async
lambda it will end up being async void
. That makes it impossible to await
as there's no task being returned. This means that everything after an await
in your lambdas will run on a different thread concurrently.
You shouldn't be passing an async
delegate to that method.
As a side note, passing a CancellationToken
doesn't enable to automatically stop the operation. It can only stop the operation before it starts or if you're observing the token somewhere inside the operation.
So, to actually use the CancellationToken
Download
should accept use it which makes the Task.Run
redundant:
await Download1Async(cts.Token);