2011-09-05 79 views
0

我正在使用TPL在MVVM应用程序中的后台线程上串行执行两个任务。在任务正在运行时,应用程序将显示一个“进度”对话框。因此,我的MVVM命令的Execute()方法首先在主视图模型中引发ImageProcessingStarting事件。该视图通过显示进度对话框来响应该事件。然后该命令启动第一个任务,继续执行第二个任务,并通过在主视图模型中引发ImageProcessingEnding事件执行最后的“继续”。该视图通过关闭进度对话框来响应该事件。代码如下。继续执行几项任务

两个后台任务都正常执行,但进度对话框在第一个任务完成后提前关闭,而不是在第二个任务完成后关闭。我希望有人能告诉我为什么,以及如何解决这个问题。谢谢你的帮助。


public void Execute(object parameter) 
{ 
    ... 

    // Announce that image processing is starting 
    m_ViewModel.RaiseImageProcessingStartingEvent(); 

    // Set up a cancellation token source 
    var tokenSource = new CancellationTokenSource(); 
    m_ViewModel.ProgressDialogViewModel.TokenSource = tokenSource; 

    // Background Task #1: Add time stamps to files 
    var task = Task.Factory.StartNew(() => this.AddTimeStampsToFiles(fileList, progressDialogViewModel)); 

    /* The Progress dialog is closing at this point! */ 

    // Background Task #2: Resequence files 
    task.ContinueWith(t => this.ResequenceFiles(fileList, progressDialogViewModel)); 

    /* The Progress dialog should close at this point. */ 

    // Announce that image processing is finished 
    task.ContinueWith(t => m_ViewModel.RaiseImageProcessingEndingEvent(), TaskScheduler.FromCurrentSynchronizationContext()); 
} 

回答

1

根据MSDN

Task.ContinueWith方法

创建执行异步目标 任务完成时延续。

这意味着当主任务完成时,两个ContinueWith调用中的其他项将相互并行运行。

为了证明这一点,您可以使用下面的代码:

System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(() => Console.WriteLine("1")); 
task.ContinueWith((t) => { System.Threading.Thread.Sleep(1000); Console.WriteLine("2"); }); 
task.ContinueWith((t) => Console.WriteLine("3")); 

输出窗口将读取:

1 
3 
2 

帮助你在你的问题,我一直使用的System.ComponentModel.BackgroundWorker来连续运行任务。有可能更好的方法,但现在这对我来说很有用。

public void Execute(object parameter) 
{ 
    BackgroundWorker bgW = new BackgroundWorker(); 

    bgW.DoWork += (s, args) => 
    { 
     AddTimeStampsToFiles(fileList, progressDialogViewModel); 
     ResequenceFiles(fileList, progressDialogViewModel); 
    }; 

    bgW.RunWorkerCompleted += (s, args) => 
    { 
     m_ViewModel.RaiseImageProcessingEndingEvent(); 
    }; 

    m_ViewModel.RaiseImageProcessingStartingEvent(); 
    bgW.RunWorkerAsync(); 
} 

对于这个工作,你可能需要传递到bgW.RunWorkerAsync()方法fileListprogressDialogViewModel值。

对于多个值,我通常使用一个Dictionary<string, object>对象,所以我可以通过名称来引用这些值。

希望这会有所帮助。

+0

那么,如何让这些任务连续运行?谢谢。 –

+0

@David Veeneman:我已根据您的意见更新了我的答案。 – fatty

0

找到我的答案了。在我的原始代码中,第二个和第三个任务都是第一个任务的延续。我更改了代码,为原始任务(taskOne)和延续任务(taskTwotaskThree)创建单独的任务。然后,taskTwo继续taskOne,并且taskThree继续taskTwo,像这样:

// Background Task #1: Add time stamps to files 
var taskOne = Task.Factory.StartNew(() => AddTimeStampsToFiles(fileList, progressDialogViewModel)); 

// Background Task #2: Resequence files 
var taskTwo = taskOne.ContinueWith(t => this.ResequenceFiles(fileList, progressDialogViewModel)); 

// Announce that image processing is finished 
var taskThree = taskTwo.ContinueWith(t => m_ViewModel.RaiseImageProcessingEndingEvent(), TaskScheduler.FromCurrentSynchronizationContext()); 

我已经接受了脂肪的答案,因为它确实提出一个可行的选择。但是,我在我的应用程序中使用了此答案中的方法,因为我正在使用TPL。