问题
Looking to chain a task to a previous instance if it exists. Currently, both are executed at the same time.
Initial code that works for one task :
private async void MenuMediaAddFiles_OnClick(object sender, RoutedEventArgs e)
{
var dialog = GetDefaultOpenFileDialog();
using (dialog)
{
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
using (var progress = new SimpleProgress(this))
{
int addFiles = await _context.AddFiles(dialog.FileNames, progress);
Console.WriteLine("Files added: {0}", addFiles);
}
}
}
}
A failed attempt to make it work :
Task<int> _files;
private async void MenuMediaAddFiles_OnClick(object sender, RoutedEventArgs e)
{
var dialog = GetDefaultOpenFileDialog();
using (dialog)
{
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
using (var progress = new SimpleProgress(this))
{
int addFiles;
Task<int> files = _context.AddFiles(dialog.FileNames, progress);
if (_files == null)
{
_files = files;
}
else
{
var task1 = await _files.ContinueWith(task => _context.AddFiles(dialog.FileNames, new SimpleProgress(this)));
}
addFiles = await _files;
Console.WriteLine("Files added: {0}", addFiles);
}
}
}
}
回答1:
You were pretty close, but there were a few things that needed to be modified:
private Task<int> previousTask = Task.FromResult(0);
private async void MenuMediaAddFiles_OnClick(object sender, RoutedEventArgs e)
{
var dialog = GetDefaultOpenFileDialog();
using (dialog)
{
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
using (var progress = new SimpleProgress(this))
{
previousTask = previousTask.ContinueWith(t =>
_context.AddFiles(dialog.FileNames, progress))
.UnWrap(); ;
int addFiles = await previousTask;
Console.WriteLine("Files added: {0}", addFiles);
}
}
}
}
Things to note:
Rather than having the previous task be
null
sometimes, it was easier to initialize it to an already completed task (Task.FromResult(0)
). This avoids the null check code.You were calling
AddFiles
twice. You shouldn't have been calling it before theif
, and you weren't ever assigning the task to the instance field inside theif
.I used
UnWrap
instead ofawait
to turn theTask<Task<int>>
into aTask<int>
. Both work, but in this case I feltUnWrap
made its intentions clearer.Note that since the entire event handler will be running in the UI thread there's no need to synchronize access to
previousTask
, if it doesn't, you'd need to do some locking.
来源:https://stackoverflow.com/questions/16285569/how-to-chain-a-task-to-a-previous-instance-of-it