2010-03-31 91 views
0

我一直在遺留應用程序上工作一段時間,並且我注意到了一些問題。該系統是一個令人難以置信的複雜的客戶端/服務器與標準和定製框架。傳統應用程序在非用戶界面線程中創建對話框

內置於應用程序中的自定義框架之一涉及驗證工作流操作。它發現潛在的錯誤,將它們分離成警告和錯誤,並將結果傳回客戶端。警告和錯誤的主要區別在於,警告會詢問用戶是否希望忽略錯誤。

我遇到的問題是,此提示符的對話框是在非ui線程上創建的,因此我們在顯示對話框時遇到了交叉線程問題。我試圖調用對話框的顯示,但是由於尚未創建窗口句柄,因此失敗。 (InvokeRequired返回false,在這種情況下,我假設它無法在其父樹中找到像樣的句柄,而不是它不需要它。)

有沒有人有任何建議可以創建此對話框並獲得UI線程來設置並調用它?

回答

1

我並不完全清楚你的實現的細節,但下面的代碼是你將如何處理來自你的非調用線程的編組調用。這段代碼片段假定「this」對象是一個windows窗體並且代表了ui線程。

這個想法是,你的非UI線程調用駐留在UI線程上的名爲「ShowMessageBox」的方法。當調用發生時,你檢查ui線程上的一個對象的this.InvokeRequired,在這個例子中它將是一個窗體。 InvokeRequired將返回「true」,這將導致if語句的第一部分中的代碼被執行。此代碼通過創建與「ShowMessageBox」方法相同簽名的委託,並重新傳遞sender對象和事件參數,調用主線程調用ShowMessageBox函數,實際上編組非線程調用到ui線程。隨後對「ShowMessageBox」方法的調用現在被「封送」到ui線程,並繞過if的第一部分,並移至else,您可以調用messagebox或窗體或任何需要的內容。

享受!

private object _lock = new object(); //should have class scope 

private void ShowMessageBox(object sender, EventArgs e) 
{ 
    if (this.InvokeRequired) 
    { 
    lock (_lock) 
    { 
     EventHandler d = new EventHandler(ShowMessageBox); 
     this.Invoke(d, new object[] { sender, e }); 
     return; 
    } 
    } 
    else 
    { 
    MessageBox.Show("Show some messsage or invoke your form instance."); 
    } 
} 
+0

這並不在這種情況下工作,正如我上面提到。沒有窗口句柄,你不能調用invoke。 – Frater 2010-03-31 02:37:09

+2

您是否考慮了上述模式並創建了一個自定義EventArgs類,該類將傳遞一個消息或枚舉類型,然後您可以使用該類型在if語句的else部分內創建表單的相應實例。這將避免您在非UI線程上創建表單的問題。您只會傳遞某種類型的指示符或消息,然後從ui線程處理該消息,而不是嘗試從除創建它之外的線程調用表單實例。 – Doug 2010-03-31 05:05:17

+0

這可能值得一試,但它會非常複雜。代碼相當可怕。我會再考慮一下,謝謝。 – Frater 2010-04-23 12:40:43

1

創建控件後。迫使它通過訪問它的處理性能,以創建手柄:

sync = new System.Windows.Forms.Control(); 
var temp = sync.Handle; 

然後,你是好去調用它:

sync.Invoke((Action)(() => { })); 
相關問題