2008-12-16 165 views
2

我的應用程序的一個要求是,如果它失去了數據庫連接,那麼它必須彈出一個大模式「無連接,稍後再試」對話框阻止所有的用戶交互,直到重新獲得連接。如何阻止UI線程從另一個線程或強制一個窗體在UI線程內運行

我通過在應用程序啓動時啓動DeviceMonitor類的一個實例來實現此目的。這個類創建一個System.Threading.Timer和每個Tick(通常1秒)以及其他一些嘗試從數據庫中繪製數據的東西。如果繪製失敗並且確定原因是由於缺少連接,則通過彈出上述對話框來處理異常。同樣,如果數據獲取成功並且對話框正在啓動,它將被強制關閉。

問題是,儘管這一切都正常,但ConnectionLost對話框不會阻止用戶與UI進行交互。這是有道理的,因爲Timer.Elapsed事件在其自己的線程中引發,並且noConnectionDialog.ShowDialog()從回調中調用,它會阻塞它所在的線程,但不會阻塞UI線程。

據我的理解,我需要強制noConnectionDialog.ShowDialog()在UI線程中運行或阻止UI線程,直到noConnectionDialog.Hide()被調用,但我不知道該怎麼做。

也許有一些其他的補救措施,或者我在這裏失去了一些東西。任何建議表示讚賞。

編輯:更多信息 - 這是一個風格化的對話框,而不僅僅是一個消息框。當我的應用程序由Castle Windsor啓動並注入到DialogFactory類中時,它會被創建。在UI界面上的按鈕被點擊時的例子 - - 因此,對話由

var d = _dialogFactory.GetNoConnectionDialog(); 
d.ShowDialog(); 

我有把這個代碼計時器經過回調外嘗試訪問並阻止UI就好從那裏,所以這是而不是表單創建的地方。

回答

1

如果你有機會到UI元素,你可以用喜歡的東西推到UI線程:

someControl.Invoke((Action)delegate { 
    MessageBox.Show(someControl, "Foo"); 
    // could also show a form here, etc 
}); 

(在MessageBox.Show的someControl幫助父母的消息框)

如果您沒有訪問UI控件,您還可以使用同步上下文:

SynchronizationContext.Current.Post(delegate { 
    MessageBox.Show("Foo"); 
}, null); 

但它更容易保持控制的保持;-p

+0

但是,這不是一個消息框。或者說它是一個程式化的消息框,所以它必須是一個完整的表單。我確實有一個包裝對話框的裝飾器,如果需要的話調用Invoke(),所以我認爲它會在UI線程上運行,但顯然它不是。 – 2008-12-16 20:32:09

2

我很確定Marc建議應該如何工作。這是我怎麼會寫它使用您的對話,而不是MessageBox

someControl.Invoke((Action)delegate { 
    var d = _dialogFactory.GetNoConnectionDialog(); 
    d.ShowDialog(); 
}, null); 

如果真的不工作我已經在我的形式和隊列使用Timer控件(System.Windows.Forms.Timer)在過去的成功

void timer_Tick(object sender, System.EventArgs e) 
{ 
    lock(queue) 
    { 
     while(queue.Count > 0) 
     { 
      Action a = queue.Dequeue(); 
      a(); 
     } 
    } 
} 

當你的設備監視器類需要顯示的UI會做到這一點:

lock(queue) 
{ 
    queue.Enqueue((Action)delegate 
    { 
     var d = _dialogFactory.GetNoConnectionDialog(); 
     d.ShowDialog(); 
    }); 
} 

與蜱的功能,看起來像這樣操作的話雖如此,我真的想重申,我認爲Marc的方法應該可以正常工作,如果您完全確定Control.Invoke不適用於您,我只能使用我的Timer +隊列方法。

0

這就是所謂的封送處理,是一個非常簡單的概念,一旦你讀它的一些好的材料(谷歌是你的朋友)。

如果你的後臺線程有一個委託調用UI線程所擁有的對象,那麼該方法(在委託的被調用端)只需將自己封送回擁有其對象的線程(這將是UI線程),然後阻止。這是非常簡單的代碼(IsInvokeRequired),你只需要瞭解如何處理。 (這基本上重述了Marc所說的,但是從更高的層面來看)。

相關問題