Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#或.NET中,是否有方法防止其他线程调用特定线程上的方法?_C#_.net_Multithreading - Fatal编程技术网

在C#或.NET中,是否有方法防止其他线程调用特定线程上的方法?

在C#或.NET中,是否有方法防止其他线程调用特定线程上的方法?,c#,.net,multithreading,C#,.net,Multithreading,我有一个带BackgroundWorker的Windows窗体应用程序。在主窗体上的方法中,会显示一个消息框,用户必须单击OK按钮才能继续。同时,在显示messagebox时,BackgroundWorker完成执行并调用RunWorkerCompleted事件。在我分配给该事件的方法(在UI线程上运行)中,在表单上调用Close方法。即使显示消息框的方法仍在运行,UI线程也不会阻止其他线程调用其上的方法。因此在表单上调用Close方法。我想要的是UI线程阻止其他线程的调用,直到带有消息框的方法

我有一个带BackgroundWorker的Windows窗体应用程序。在主窗体上的方法中,会显示一个消息框,用户必须单击OK按钮才能继续。同时,在显示messagebox时,BackgroundWorker完成执行并调用RunWorkerCompleted事件。在我分配给该事件的方法(在UI线程上运行)中,在表单上调用Close方法。即使显示消息框的方法仍在运行,UI线程也不会阻止其他线程调用其上的方法。因此在表单上调用Close方法。我想要的是UI线程阻止其他线程的调用,直到带有消息框的方法完成。有简单的方法吗?

使用ManualResetEvent来控制RunWorkCompleted事件和显示MessageBox的方法之间的同步。

您可以使用简单的
锁来实现这一点。在表单中,创建一个表单级成员,如下所示:

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

private void ShowSomeMessage()
{
    lock (_locker)
    {
        MessageBox.Show("message");
    }
}
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;
}
然后让您的代码在两种方法中都获得锁,如下所示:

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

private void ShowSomeMessage()
{
    lock (_locker)
    {
        MessageBox.Show("message");
    }
}
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;
}
如果您的代码当前在
ShowSomeMessage()
中阻塞(即消息框仍然打开),
RunWorkerCompleted()
方法将等待消息框关闭(释放锁)后再关闭表单

更新:无论哪个线程调用什么,这都应该有效:

private bool _showingMessage = false;
然后让您的代码在两种方法中都获得锁,如下所示:

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

private void ShowSomeMessage()
{
    lock (_locker)
    {
        MessageBox.Show("message");
    }
}
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;
}

我认为你应该在处理事件的方式上更加自律。您不希望停止在UI线程上调用方法,因为方法调用机制与允许鼠标和键盘事件等工作的机制相同。如果您阻止方法调用,您也将阻止该调用。相反,您需要以某种方式延迟这些方法。您可能需要编写自己的同步代码来执行此操作。

这是我最初尝试的。但它不起作用,因为我相信,这两个方法运行在同一个线程上。当RunWorkerCompleted()到达lock语句时,它不会阻塞,因为它运行的线程已经有了锁。如果我错了,请纠正我。这听起来不对,除非通过
Invoke
BeginInvoke
调用其中一个方法。如果消息框是通过单击按钮显示的,那么它将位于UI线程上,这应该与后台工作线程不同。我也尝试了第二种方法。这有点管用。但它也有斯图尔特提到的问题。UI线程无法响应鼠标单击,因此用户无法单击“确定”。它会导致一种“死锁”。