2013-03-27 149 views
2

這是我的代碼。C#:方法被連續調用兩次

BackgroundWorker exportWorker = new BackgroundWorker(); 

private void btnOK_Click(object sender, RoutedEventArgs e) 
{ 
    exportWorker.DoWork += new DoWorkEventHandler(ExportWorkerDoWork); 
    exportWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ExportWorkerRunWorkerCompleted); 
    exportWorker.RunWorkerAsync(); 
} 


void ExportWorkerDoWork(object sender, DoWorkEventArgs e) 
{ 
    MethodToPerformInThisThread(); 
    **Dispatcher.Invoke(new Action(() => {MethodofAnotherThreadThatChangesUIStuff();}** 
} 

void ExportWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
} 
  • 當我點擊確定按鈕(btnOK_Click)第一次,它會提前 並運行一切就好了。現在
  • ,如果我確定按鈕點擊第二次代碼有 執行完畢,在大膽的運行代碼的兩倍,這意味着 方法MethodofAnotherThreadThatChangesUIStuff();被稱爲連續兩次 後。
  • 再次,如果我第三次單擊確定按鈕, MethodofAnotherThreadThatChangesUIStuff();被連續調用三次 。
  • 等等。

我想MethodofAnotherThreadThatChangesUIStuff();被調用一次,不管它是哪一次點擊。我的意思是,通常情況就是這樣。

我在這裏錯過了什麼?

任何幫助將非常感激。

+0

也許禁用點擊方法中的按鈕。 – RyPope 2013-03-27 18:56:27

+0

我看到EventHandlers的一些粗心的處理 – 2013-03-27 18:59:17

回答

2

這正在造成的,因爲這條線:

exportWorker.DoWork += new DoWorkEventHandler(ExportWorkerDoWork); 

正在btnOK_Click處理程序中運行。如果你設置這樣的處理程序以外的事件:

BackgroundWorker exportWorker = new BackgroundWorker(); 
exportWorker.DoWork += new DoWorkEventHandler(ExportWorkerDoWork); 
exportWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ExportWorkerRunWorkerCompleted); 

private void btnOK_Click(object sender, RoutedEventArgs e) 
{ 
exportWorker.RunWorkerAsync(); 
} 

然後一切都應該像你期望的那樣工作。

另一種選擇實際上是在btnOK_Click處理程序中創建一個新的BackgroundWorker。從本質上講,你將爲每次點擊創建一個新的工作者,用處理程序設置它,然後運行它。然後,您將丟棄它併爲每次點擊創建一個新的。

9

由於您在每次按下按鈕時都聲明瞭Click處理程序之外的背景,所以您需要再次添加事件處理程序。這就是爲什麼你的方法第二次被調用兩次,第三次它會被調用三次...

要解決這個問題,請在click方法之外添加事件處理程序(例如在構造函數中),並且只留下RunAsync()調用click方法。

+0

取消訂閱事件處理程序在這種情況下並不理想,因爲在取消訂閱處理程序之前,該方法可能會再次開始執行...... – 2013-03-27 19:02:05

+0

正確...錯過了這個小事實。 ;) – IAbstract 2013-03-27 19:09:49

3

每次單擊「確定」時,都會創建新的事件處理程序,這些處理程序將全部調用您的DoWork方法。

將此代碼放在應用程序的初始化:

exportWorker.DoWork += new DoWorkEventHandler(ExportWorkerDoWork); 
exportWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ExportWorkerRunWorkerCompleted); 

只有在您btnOK_Click方法如下:

exportWorker.RunWorkerAsync();