2011-09-05 74 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。