How to chain a task to a previous instance of it?

寵の児 提交于 2019-12-08 14:48:38

问题


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 the if, and you weren't ever assigning the task to the instance field inside the if.

  • I used UnWrap instead of await to turn the Task<Task<int>> into a Task<int>. Both work, but in this case I felt UnWrap 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!