Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无阻塞的顺序异步任务_C#_Wpf_Asynchronous - Fatal编程技术网

C# 无阻塞的顺序异步任务

C# 无阻塞的顺序异步任务,c#,wpf,asynchronous,C#,Wpf,Asynchronous,我有一个C#WPF应用程序,它使用了一种非常简单的MVVM方法。在其中一个ViewModels中,我希望按顺序运行一系列任务,但希望运行每个异步到主线程。我希望能够报告任务之间的进度,但我不希望在任何任务运行时阻塞GUI 是否有实现这一目标的标准方法,或“最佳实践” 我已经实现了一些利用了BackgroundWorker的东西,这让我感到既高兴又有点害怕。启动整个过程的代码让人感觉特别不舒服。我觉得必须有一种更好的方法,或者至少是一种既定的方法来做到这一点 非常感谢你的建议 丹 以下是拼凑在一

我有一个C#WPF应用程序,它使用了一种非常简单的MVVM方法。在其中一个ViewModels中,我希望按顺序运行一系列任务,但希望运行每个异步到主线程。我希望能够报告任务之间的进度,但我不希望在任何任务运行时阻塞GUI

是否有实现这一目标的标准方法,或“最佳实践”

我已经实现了一些利用了
BackgroundWorker
的东西,这让我感到既高兴又有点害怕。启动整个过程的代码让人感觉特别不舒服。我觉得必须有一种更好的方法,或者至少是一种既定的方法来做到这一点

非常感谢你的建议


以下是拼凑在一起的选项:

protected void runAsyncTask(SequentialTask seqTask)
    {
        if (HasErrored) return;

        DoWorkEventHandler worker = (s, e) =>
        {
            setTaskStartStatusMessage(seqTask.TaskMessage);
            ShowProgress = true;
            seqTask.Task((BackgroundWorker)s);
        };

        ProgressChangedEventHandler progress = (s, e) =>
        {
            if (seqTask.TaskProgress != null)
                seqTask.TaskProgress(e.ProgressPercentage, e.UserState);
        };

        RunWorkerCompletedEventHandler done = null;
        done = (s, e) =>
        {
            ShowProgress = false;
            if (e.Error != null)
            {
                HasErrored = true;
                displayTaskExceptionMessage(e.Error, seqTask.TaskMessage);
            }
            else
            {
                setTaskCompleteStatusMessage(seqTask.TaskMessage);
                if (seqTask.TaskComplete != null)
                    seqTask.TaskComplete();
            }
            ((BackgroundWorker)s).RunWorkerCompleted -= done;
            ((BackgroundWorker)s).DoWork -= worker;
            ((BackgroundWorker)s).ProgressChanged -= progress;

            if (seqTask.NextTask != null && (seqTask.CanExecuteNext == null ? true : seqTask.CanExecuteNext()))
                runAsyncTask(seqTask.NextTask);
        };

        if (seqTask.TaskProgress != null)
            backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.DoWork += worker;
        backgroundWorker.RunWorkerCompleted += done;
        backgroundWorker.ProgressChanged += progress;
        backgroundWorker.RunWorkerAsync();
    }
SequentialTask
只是一组简单的属性:

public class SequentialTask
{
    public Action<BackgroundWorker> Task { get; set; }
    public String TaskMessage { get; set; }
    public Func<bool> CanExecuteNext { get; set; }
    public Action<int, object> TaskProgress { get; set; }
    public Action TaskComplete { get; set; }
    public SequentialTask NextTask { get; set; }
}

等等。

我认为你的方法没有任何问题。最重要的是:它可以工作。

您看过.NET4.0中的任务并行库(TPL)了吗?这允许您执行以下操作:

Task firstTask = new Task(()=>RunStepOne());
firstTask.ContinueWith(task=>()=>RunSecondStep());
firstTask.Start();

创建、继续和停止TPL上构建的任务有很多选项。当然值得一看。

协同程序或反应式框架非常适合这样做:嗨,Jay,谢谢你的链接-快速浏览一下,我肯定会花时间想一想,但我认为Adam的TPL建议是我最初努力的方向。更不用说,这会在C#5发布时帮你一把。谢谢Adam,简言之,这是C#的下一章——我会继续看下去。从您展示的代码片段来看,它显然比链接递归结构要干净得多。我认为这肯定能满足我的需要,而且是“开箱即用”,再次感谢。
Task firstTask = new Task(()=>RunStepOne());
firstTask.ContinueWith(task=>()=>RunSecondStep());
firstTask.Start();