C# 这是.net Monitor/lock语句中的错误还是MessageBox.Show的行为有所不同?

C# 这是.net Monitor/lock语句中的错误还是MessageBox.Show的行为有所不同?,c#,.net,locking,monitor,C#,.net,Locking,Monitor,假设您在win表单上有两个按钮。您认为当用户按下面代码的“按钮1”时应该是什么行为 它应该一次显示所有5个消息框,还是逐个显示-MessageBox.Show语句在lock语句中 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private static readonly object lockobject = new object();

假设您在win表单上有两个按钮。您认为当用户按下面代码的“按钮1”时应该是什么行为

它应该一次显示所有5个消息框,还是逐个显示-MessageBox.Show语句在lock语句中

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private static readonly object lockobject = new object();

    private void button1_Click(object sender, EventArgs e)
    {
        var action = new Action(function);
        for(int i = 0; i< 5; i++)
        {
            action.BeginInvoke(null, null);
        }
    }

    private void function()
    {
        if (button2.InvokeRequired)
        {
            var func = new Action(function);
            button2.Invoke(func);
        }
        else
        {
            lock (lockobject)
            {
                MessageBox.Show("Testing");
            }
        }
    }
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
}
私有静态只读对象lockobject=新对象();
私有无效按钮1\u单击(对象发送者,事件参数e)
{
var动作=新动作(功能);
对于(int i=0;i<5;i++)
{
action.BeginInvoke(null,null);
}
}
私有空函数()
{
如果(按钮2.需要调用)
{
var func=新操作(函数);
按钮2.调用(func);
}
其他的
{
锁定(锁定对象)
{
MessageBox.Show(“测试”);
}
}
}
}

现在,如果我们用任何其他语句替换MessageBox.Show,它将一次只执行一条语句,其他线程将等待,一次执行一条。

我怀疑UI线程在MessageBox生命周期中正在发送消息。由于锁是可重入的(并且UI线程每次都在运行代码),这导致了上述问题。也许可以尝试将所有者(
)传递到消息框中?(我马上就来试试……)


您可以更有力地阻止它,但这将阻止绘制(“不响应”等)。

因为当InvokeRequired为false时执行lock语句,所以锁都将在同一(主)线程上运行。因此,锁不会阻塞

如果要阻止MessageBox,请改用ShowDialog

  • 只有当另一个线程拥有锁时,锁才会被阻塞,允许多次从同一线程锁定同一对象——否则这将是一个即时死锁,毕竟它会在等待当前线程时阻塞当前线程

  • Control.BeginInvoke不会在不同的线程中执行代码,它将始终执行线程中的代码,为控件泵送消息,它通过将消息发布到控件的输入队列,然后在消息到达时执行代码来执行


  • 因为2你的代码根本不是多线程的,所有的东西都在同一个线程中执行——这让我们回到1,当你没有多个线程时,锁什么都不做。

    我同意Nir。将函数更改为下面的函数后,可以测试您是否在同一线程上运行(毫不奇怪):


    因此,这里因为您的UI线程欠锁,所以它不会被阻止。归根结底,STA线程与正确的多线程编程不兼容。

    MessageBox上没有ShowDialog谢谢大家的回答,伙计们,我知道我现在错在哪里了。干杯
    private void function()
    {
       if (button2.InvokeRequired)
       {
            var func = new Action(function);
            button2.Invoke(func);
       }
       else
       {
            lock (lockobject)
            {
                int threadId = Thread.CurrentThread.ManagedThreadId;
                MessageBox.Show("Testing. Running on thread "+threadId);
            }
        }
    }