2010-04-30 61 views
4

我有一個Windows Forms應用程序與BackgroundWorker。在主窗體上的一個方法中,顯示一個MessageBox,用戶必須點擊OK按鈕繼續。同時,在顯示消息框時,BackgroundWorker完成執行並調用RunWorkerCompleted事件。在我已經分配給在UI線程上運行的事件的方法中,將在窗體上調用Close方法。即使顯示消息框的方法仍在運行,UI線程也不會阻止其他線程調用它的方法。所以Close方法在窗體上被調用。我想要的是UI線程阻止其他線程的調用,直到消息框的方法結束。有沒有簡單的方法來做到這一點?在C#或.NET中,是否有辦法阻止其他線程調用特定線程上的方法?

回答

1

我想你應該更關心你的事件如何處理。您不想停止在UI線程上調用的方法,因爲方法調用機制與允許鼠標和鍵盤事件等工作的方法調用機制相同。如果你阻止方法調用,你也會阻止它。相反,您需要以某種方式延遲方法。您可能需要編寫自己的同步代碼才能執行此操作。

0

使用ManualResetEvent控制RunWorkCompleted事件和顯示MessageBox的方法之間的同步。

0

對此,您可以使用簡單的lock。在您的形式,像這樣創建窗體級成員:

private object _locker = new object(); 

然後讓你的代碼獲取兩種方法的鎖,就像這樣:

private void RunWorkerCompleted() 
{ 
    lock (_locker) 
    { 
     this.Close(); 
    } 
} 

private void ShowSomeMessage() 
{ 
    lock (_locker) 
    { 
     MessageBox.Show("message"); 
    } 
} 

如果你的代碼是目前在ShowSomeMessage()阻塞(即消息框仍然打開),RunWorkerCompleted()方法將在關閉表單之前等待消息框關閉(釋放鎖定)。

更新:這應該工作,無論哪個線程正在調用什麼:

private bool _showingMessage = false; 

然後讓你的代碼獲取鎖在兩種方法中,像這樣:

private void RunWorkerCompleted() 
{ 
    while (_showingMessage) 
    { 
     Thread.Sleep(500); // or some other interval (in ms) 
    } 
    this.Close(); 
} 

private void ShowSomeMessage() 
{ 
    _showingMessage = true; 
    MessageBox.Show("message"); 
    _showingMessage = false; 
} 
+0

這是我最初嘗試過的。但它不起作用,因爲我相信這兩種方法在同一個線程上運行。並且,當RunWorkerCompleted()獲取到鎖語句時,它不會因爲它所運行的線程已經擁有該鎖而被阻塞。如果我錯了,請糾正我。 – YWE 2010-04-30 19:18:12

+0

這聽起來不對,除非通過'Invoke'或'BeginInvoke'調用這些方法之一。如果從按鈕單擊中顯示消息框,則該消息框位於UI線程上,該線程應該與後臺工作線程不同。 – MusiGenesis 2010-04-30 19:24:21

+0

我也嘗試過第二種方式。它有點作品。但它遭受了Stewert提到的問題。 UI線程無法響應鼠標點擊,因此用戶無法單擊確定。它導致了一種「僵局」。 – YWE 2010-04-30 19:47:49

相關問題