我有一个使用相当简单的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()
{
等
答案 0 :(得分:7)
你看过.NET 4.0中的任务并行库(TPL)吗?这允许你做这样的事情:
Task firstTask = new Task(()=>RunStepOne());
firstTask.ContinueWith(task=>()=>RunSecondStep());
firstTask.Start();
有很多选项可用于创建,继续和停止在TPL上构建的任务。这当然值得一看。
答案 1 :(得分:0)
我认为你的方法没有任何问题。最重要的是:它有效。