Reputation: 1833
I use async commands based on https://msdn.microsoft.com/en-us/magazine/dn630647.aspx
An executor of the command looks like this:
(package) =>
{
return Task.Run(() =>
{
dataProvider.Save(package);
// emulate long running operation
for (int i = 0; i < 5000000; ++i)
{
string[] ar = new string[1000];
}
}).ContinueWith(t =>
{
messagingService.Send(new PackageSavedMessage
{
Id = package.Id,
Name = package.Name,
});
}, TaskScheduler.FromCurrentSynchronizationContext());
It works well when I click on save button in the application, i.e. it asynchronously waits, then ContinueWith fires.
But when I try to call it from unit test
[Test]
public async Task SaveCommand_Test()
{
using (var scope = _container.BeginLifetimeScope())
{
var vm = scope.Resolve<MainViewModel>();
AsyncCommandBase acb = vm.PackageViewModels[0].SaveCommand as AsyncCommandBase;
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
await acb.ExecuteAsync(package);
}
}
ContinueWith fires immediately, not waiting for task finished
If I don't set SynchronizationContext, I get an error
The current SynchronizationContext may not be used as a TaskScheduler.
Upvotes: 0
Views: 152
Reputation: 457472
Your executor shouldn't need to use ContinueWith
; a more modern await
would work just as well (note that await
will automatically capture and resume its context, so no explicit TaskScheduler
is necessary):
async (package) =>
{
await Task.Run(() =>
{
dataProvider.Save(package);
// emulate long running operation
for (int i = 0; i < 5000000; ++i)
{
string[] ar = new string[1000];
}
});
messagingService.Send(new PackageSavedMessage
{
Id = package.Id,
Name = package.Name,
});
}
Upvotes: 2