2016-04-06 26 views
1

背景當單擊一個選項卡並調用Parallel.Invoke時InvalidOperationException?

我一個人誰是很新的C#中做線程/併發操作,並正與跨線程的GUI應用程序掙扎。目前我正在遇到運行時拋出的異常,我不知道該如何處理。首先,我將提供正在發生的事情的背景,然後描述我嘗試調試的內容。

我有一個任務,執行一堆計算。

readingDumpTask = new Task(() => 
{ 
    this.myDumpEntries = BiteDump.GetEntriesFromFile(fileName); 
}); 

當這項任務完成後,我想一次做兩件事。我實現了這個過程中,以下列方式...

// display dump information 
displayDumpTask = readingDumpTask.ContinueWith(
    delegate 
    { 
     Parallel.Invoke 
     (
      () => this.DisplayEntries(), 
      () => this.DisplayDump() 
     ); 
    } 
, TaskScheduler.FromCurrentSynchronizationContext()); 

這兩種方法正在委託,在下面的工作方式......

方法#1

private void DisplayEntries() 
{ 
    UpdateUIDelegate myDel = new UpdateUIDelegate(this.DisplayEntries); 

    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(myDel); 
    } 

    // fills some data into labels on the GUI 
} 

方法#2

private void DisplayDump() 
{ 
    UpdateUIDelegate myDel = new UpdateUIDelegate(this.DisplayDump); 

    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(myDel); 
    } 

    // fills some data into a RTB on the GUI 
} 

我想說清楚方法#1使用的控件都不會被方法#2觸及。

問題陳述

這裏的問題是,我只要我嘗試從DisplayDump函數內訪問控件得到一個InvalidOperationException。我點擊轉儲選項卡時,我只會遇到此異常,如下所示。

Form Design

我認爲這事做的事實,該DisplayDump方法訪問文本框坐在轉儲標籤內。現在,當我在導航選項卡上時,我從來沒有遇到任何問題,一切都安全/合理。

嘗試調試

我纔剛剛今天上午發現了怎麼就沒看到並行任務調試窗口更不用說真正知道如何使用它來解決我的問題。所以,我已經從Parallel.Invoke塊中刪除了其中一個方法調用,並且我發現它與哪個選項卡無關,在這種情況下我永遠不會遇到異常(DisplayDump始終有效)。但是,只要我在Parallel聲明中採取了兩項操作,就會出現問題。所以......到目前爲止,我所知道的是它與Parallel.Invoke有關。

enter image description here

+1

順便說一句,這樣的方法絕對沒有必要使用'Parallel.Invoke',因爲'BeginInvoke'無論如何都會在UI線程上序列化它們。 –

+0

@IvanStoev我不太確定,並行調用將操作放在單獨的處理器上。我已經測試過這個功能。當你說「在UI上對它們進行序列化」時,你會讓它聽起來像是一個接一個地執行這些動作。我不想誤解你,你能否詳細說明一下? – Snoopy

+0

當方法調用'BeginInvoke'時,委託在UI線程上被調度。然後,UI線程將一個接一個地執行預定的委託,一次。 –

回答

0

後你調用BeginInvoke,你的方法應返回。如果你沒有返回,那麼GUI將在非UI線程上訪問,你將得到一個InvalidOperationException。

private void DisplayEntries() 
{ 
    UpdateUIDelegate myDel = new UpdateUIDelegate(this.DisplayEntries); 

    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(myDel); 
     return; // ** change here 
    } 

    // fills some data into labels on the GUI 
} 
+0

Ahh right ...那麼爲什麼在我的調試窗口中,DisplayDump有一個不同的「線程賦值」號碼,而不是DisplayEntries和ButtonClick(顯示在我的底部圖像中)? – Snoopy

相關問題