2010-05-30 33 views
1

我一直在編程C#一段時間(我是一名計算機科學專業),並且從未必須實現線程。WPF BackgroundWorker執行

我目前正在爲需要線程執行一系列操作的客戶端構建一個應用程序。

由於客戶/供應商協議的性質,我無法發佈我正在使用的源代碼。我發佈的代碼是一般形式。幾乎是我正在實施的基本想法,不包括內容特定的來源。

第一個片段演示了我的基本結構,

進展類是顯示一個對話框,以防止用戶的交互UI自定義進度窗口。

我目前正在使用代碼來完成基於應用程序代碼的另一個區域中的對象集合的數據庫調用。

例如,我有一個我的自定義類的「對象」的集合,即我或代表執行這些數據庫調用。當我稱之爲「GeneralizedFunction」並且只有一次時,我目前的設置工作得很好。

我需要做的是對集合中的每個對象調用一次該函數。我試圖使用foreach循環遍歷集合,然後我嘗試了一個for循環。

對於兩個循環,結果都是一樣的。 Async操作完全按照集合中第一個項目的要求執行。但是,這是它唯一的作用。對於每個後續項目,進度框(我的自定義窗口)都會顯示並立即關閉。

就數據庫調用而言,集合中第一個項目的調用是唯一成功完成的調用。所有其他人都沒有嘗試。

我已經嘗試了一切,我知道並不知道要做,但我似乎無法得到它的工作。

我怎樣才能讓我的整個系列工作?

任何和所有的幫助非常感謝。

Progress progress; 

BackgroundWorker worker; 

// Cancel the current process 
private void CancelProcess(object sender, EventArgs e) 
{ 
worker.CancelAsync(); 
} 

// The main process ... "Generalized" 
private void GeneralizedFunction() 
{ 
progress = new Progress(); 
progress.Cancel += CancelProcess; 
progress.Owner = this; 

Dispatcher pDispatcher = progress.Dispatcher; 

worker = new BackgroundWorker(); 
worker.WorkerSupportsCancellation = true; 

object[] workArgs = { arg1, arg2, arg3}; 

worker.DoWork += delegate(object s, DoWorkEventArgs args) 
{ 
    /* All main logic here 

    */ 

    foreach(Class ClassObject in ClassObjectCollection) 
    { 
    //Some more logic here 

    UpdateProgressDelegate update = new UpdateProgressDelegate(updateProgress); 

    pDispatcher.BeginInvoke(update, arg1,arg2,arg3); 
    Thread.Sleep(1000); 
    } 
}; 
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
{ 
    progress.Close(); 
}; 

worker.RunWorkerAsync(workArgs); 
progress.ShowDialog(); 
} 

public delegate void UpdateProgressDelegate(arg1,arg2,arg3); 

private void updateProgress(arg1,arg2,arg3) 
{ 
//Update progress 
} 
+0

澄清請:上面的代碼示例中的'foreach'循環,按預期工作?還是有一個外部循環重複調用'GeneralizedFunction'? – 2010-05-30 11:16:41

+0

簡單的WPF進度窗口取消 http://blog.quantumbitdesigns.com/2008/07/22/simple-wpf-progress-window-with-cancellation/ – abmv 2010-05-30 12:10:28

回答

1

好的,所以你有一個運行在DoWork處理程序中的後臺進程。該線程產生了許多其他線程(使用BeginInvoke),然後休眠1秒。 (爲什麼睡眠(1000)?)

似乎沒有嘗試等待UpdateProgressDelegate線程在for循環之後完成。因此,當某些pDispatchers仍在執行時,您將調用progress.Close();

我也看不到Bgw和對話框之間的任何通信。

這裏的快速修復不會調用循環內的BeginInvoke,而是執行bgw線程中的所有邏輯。首先讓它工作。和一個提示:真正的程序不睡眠()

然後,如果你想產生更多的線程,你需要實現一些rendez虛擬邏輯。使用EventWaitHandle類或其他類。

請注意,這在.NET 4中變得非常容易(使用Parallel。ForEach)

+0

我認爲你讀錯了,有一個'每個'BackgroundWorker'的新進度對話框,並且每個工作人員在完成其工作並關閉其進度之前循環所有內容。 – 2010-05-30 11:39:38

+0

@Aviad,你可能是對的,但是IO在DoWork()內的循環內部看到一個BeginInvoke。但真正的問題可能與Db的東西(未顯示)。 – 2010-05-30 13:23:22

0

progress.Close()上設置斷點以查看它是否正在調用(導致進度窗口消失)。您可能需要撥打DispatcherOperation.Wait()以確保在完成所有ASYNC工作之前DoWork()不會退出。 BeginInvoke()返回DispatcherOperation - 你需要使用它來加入這些線程並等待它們完成。

您可能需要保留所有調用的DispatherOperations(pDispatcher.BeginInvoke(update,arg1,arg2,arg3))的列表。在foreach循環之後,您只需等待每個完成。我認爲問題在於RunWorkerCompleted正在觸發,因爲您並未等待DispatchOperation完成(因此關閉進度窗口)。

相關問題