I have to debug code by a former colleague. The application is part of a machine control. The machine is already delivered to our customer, which restricts my debugging abilities.
The situation is as follows: A Windows Forms MessageBox is shown:
if (MessageBox.Show(toask, "Überprüfung", MessageBoxButtons.OKCancel, MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly)
!= DialogResult.OK)
{
// Do something here
return;
}
The user does not click the box away for at least half a minute, because he has to do something, when the box is shown. Meanwhile, I need the callback method of a System.Timers.Timer (500 ms, AutoReset == false) event to be executed:
private void timerLoop_Elapsed(object sender, ElapsedEventArgs e)
{
Action updateUI = () =>
{
// Do some extensive work, accessing Windows Forms controls.
// I'm expecting a bool variable to be set here.
}
if (this.InvokeRequired)
this.Invoke(updateUI);
else
updateUI();
timerLoop.Start();
}
The bool variable mentioned in the code block is not set, although it should be.
Since the callback method is always executed in a thread other than the UI thread, this.Invoke(updateUI)
is called (probably could get rid of if(this.InvokeRequired)
).
My question is: is the invoked updateUI
blocked from executing, while the MessageBox is shown? This would explain the applications behavior.
And if so, what can I do to force the callback's execution while MessageBox is shown?
Would BeginInvoke()
help?
ADDENDUM 1: The timer was formerly a Windows.Forms.Timer instead of a Systems.Timers.Timer. I changed it trying to solve another issue. Before that, the application worked in the situation described above (apart from other issues).
Seems, this info is relevant for the question? However, I don't understand why the Forms.Timer's callback is handled during MessageBox, but not the Control.Invokes in the Timers.Timers callback?
I had the idea to test my theory with a little test application:
namespace Timers_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timersTimer.Elapsed += OnElapsed;
winFormsTimer.Start();
timersTimer.Start();
}
private System.Timers.Timer timersTimer = new System.Timers.Timer(500);
private void winFormsTimer_Tick(object sender, EventArgs e)
{
tBFormsTimer.Text = DateTime.Now.ToString("hh:mm:ss");
}
private void OnElapsed(object sender, ElapsedEventArgs e)
{
tBTimersTimer.Invoke((Action)(() => tBTimersTimer.Text = DateTime.Now.ToString("hh:mm:ss")));
}
private void btnMessageBox_Click(object sender, EventArgs e)
{
MessageBox.Show("Which Callbacks does this MessageBox block?", "Test", MessageBoxButtons.OK, MessageBoxIcon.Question);
}
}
}
Screenshot of the running application.
This answers the question: My observation is, that the action in Control.Invoke(Action)
is NOT blocked until after clicking away the MessageBox, at least not categorically.