2010-04-30 63 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

相关问题