顺序异步任务没有阻塞

时间:2010-11-09 14:19:27

标签: c# wpf asynchronous

我有一个使用相当简单的MVVM方法的C#WPF应用程序。在其中一个ViewModel中,我希望按顺序运行一系列任务,但是希望将每个异步运行到主线程。我希望能够在任务之间报告进度的粒度,但我不希望在任何任务运行时阻止GUI。

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

我已经实现了一些利用BackgroundWorker的东西,我感到很高兴和温和的恐惧。把整个事情搞砸的代码感觉特别是非C#ish。我觉得必须有一个更好的,或者至少是一种既定的方法。

非常感谢您的建议。


这是拼凑在一起的选项:

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; }
}

这导致了类似Perl的语法:

runAsyncTask(new SequentialTask()
        {
            Task = (x) => loadFile(),
            TaskMessage = "Load File",
            CanExecuteNext = null,
            NextTask = new SequentialTask()
            {
                Task = (x) => validateImport(),
                TaskMessage = "Validate Input Lines",
                TaskComplete = () =>
                {
                    if (!ImportIsValid)
                        displayValidationMessages();
                },
                CanExecuteNext = () => ImportIsValid,
                NextTask = new SequentialTask()
                {

2 个答案:

答案 0 :(得分:7)

你看过.NET 4.0中的任务并行库(TPL)吗?这允许你做这样的事情:

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

有很多选项可用于创建,继续和停止在TPL上构建的任务。这当然值得一看。

答案 1 :(得分:0)

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