Is this a bug in the .net Monitor / lock statement or the MessageBox.Show behaves differently?

Imagine that you have two buttons in the form of a win. What do you think should be the behavior when the user clicks the "1" button using the code below?

Should it display all 5 message boxes at a time or one after another - is the MessageBox.Show expression inside the lock statement?

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"); } } } } 

Now, if we replace MessageBox.Show with any other status, it will execute the operator only one at a time, the rest of the threads will wait one at a time.

+4
source share
4 answers

Since your lock statement is executed when InvokeRequired is false, locks will be executed on the same (main) thread. Therefore, locks will not be blocked.

If you want the MessageBox to block, use ShowDialog instead.

+4
source
  • A lock is blocked only if another thread owns the lock, it is allowed to lock on the same object from the same thread several times - otherwise it would be an instant deadlock, because it would block the current thread while waiting for the current flow.

  • Control.BeginInvoke does not execute code in another thread, it will always execute code in the message flow for the control, it does this by sending a message to the control input queue, and then executing the code when a message arrives.

because of 2, your code is not multithreaded at all, everything is executed in one thread - and this brings us back to 1, when you do not have blocking of several threads, it does nothing.

+2
source

I suspect that the UI thread forwards messages during the MessageBox life cycle. Since the locks are repeated (and the user interface thread runs the code each time), this causes the above. Perhaps try passing the owner ( this ) to the message box? (I will try in a second ...) .

You can block it more intensively, but it will block the drawing ("not responding", etc.).

0
source

I agree with Nir. After you change your function to the one below, you can check that you are working in the same thread (not surprisingly):

 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); } } } 

So, here, because your UI thread is blocking, it is not blocking. The bottom line is that STA threads are not compatible with proper multithreaded programming.

0
source

All Articles