using form.showdialog to control modal window

T

TS

I want to be able to display a modal window during my application used to
take tests. The application has a looping timer that after each time it's
interval elapses, an event is raised that checks the db to see if a field in
a table is marked as being paused meaning someone in my other app has marked
the test as being paused. i want the modal window to pop up if so, unless
the window is already displayed becuase of the last time the timer elapsed.
I want the modal window to dissappear if it is visible and the test has been
un-paused. I have it working except that for some reason after the first
call to showDialog(), the code doesn't continue to execute the rest of the
method, instead it starts back at the top again. There are no exceptions
that are being thrown becuase it is wrapped in a try/catch. When the code at
the beg. of the method begins again, the reference to the modal form that is
modularly declared is null. After the 2nd time thru the method, everything
works as expected.

Why is this?

this is the event that is fired when the timer's interval is gone on the
main form.
private void TerminateTimer_Tick(object sender, EventArgs e)
{
try
{
string status = this.MyController.GetApplicantStatus();

if( status == "H" ) //Hold
{
if(this.pause == null)
{
pause = new Pause();
pause.ShowDialog();
}
}
else if( status == "T" ) //Terminated
{
if(this.pause != null)
pause.Close();

this.terminateTimer.Stop();
this.MyController.TerminateSession();
}
else
{
if(this.pause != null)
{
pause.Close();
pause.Dispose();
}
}

string x="asdfasdf";

}
catch(Exception ex)
{
ReportException(ex);
}
}

this is the form that is displayed as a modal window:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using Shared.ResourceHelper;

namespace TestStationUI
{
/// <summary>
/// Summary description for Pause.
/// </summary>
public class Pause : System.Windows.Forms.Form
{
private System.Windows.Forms.Label lblPauseMessage;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Pause()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblPauseMessage = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// lblPauseMessage
//
this.lblPauseMessage.Location = new System.Drawing.Point(32, 40);
this.lblPauseMessage.Name = "lblPauseMessage";
this.lblPauseMessage.Size = new System.Drawing.Size(216, 40);
this.lblPauseMessage.TabIndex = 0;
//
// Pause
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.lblPauseMessage);
this.Name = "Pause";
this.Text = "Pause";
this.Load += new System.EventHandler(this.Pause_Load);
this.ResumeLayout(false);

}
#endregion

private void Pause_Load(object sender, System.EventArgs e)
{
this.lblPauseMessage.Text =
ResManager.GetText(this.lblPauseMessage.Name);
}

}
}
 
J

jer_m

Hi TS,
the code doesn't continue to execute the rest of the method

ShowDialog() is a blocking call(its not really but it pretends to be).
When you call ShowDialog, your going to sit at that point waiting for
the dialog to close, returning a DialogResult.
instead it starts back at the top again

Your code isn't starting at the top of the function. What you are
seeing is another call thats just been made.

As a test, in your timer function just keep creating new forms, dont
close them. Each time Call showdialog, then show a message box.
If you wait untill 5 forms are all showing at the same time, you won't
have seen any message boxs. As you close all of them, you will see 5
message boxs.
After the 2nd time thru the method, everything works as expected. Why
is this?

It works the second time through because you designed your state
machine well. The problem is your code is designed to run in a loop,
and the timer event that your using is close to a loop, but it's not.

would this work for you instead?

private EventHandler SomeCallback;

protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);

this.SomeCallback = new EventHandler(this.SomeEventHandler);
new System.Threading.Thread(new
System.Threading.ThreadStart(SomeThread)).Start();
}

public void SomeThread()
{
while ( true )
{
string status = this.MyController.GetApplicantStatus();

if( status == "H" ) //Hold
{
if(this.pause == null)
{
this.BeginInvoke(SomeCallback);
}
}
else if( status == "T" ) //Terminated
{
if(this.pause != null)
pause.Close();

this.terminateTimer.Stop();
this.MyController.TerminateSession();
}
else
{
if(this.pause != null)
{
pause.Close();
pause.Dispose();
}
}
string x="asdfasdf";

System.Threading.Thread.Sleep(5000); //TerminateTimer.Interval
}
}

private void SomeEventHandler(object s, System.EventArgs e)
{
pause = new Pause();
pause.ShowDialog();
}

Kind Regards,
Jerron
 
T

TS

thanks, i think my problem is now fixed!

jer_m said:
Hi TS,


ShowDialog() is a blocking call(its not really but it pretends to be).
When you call ShowDialog, your going to sit at that point waiting for
the dialog to close, returning a DialogResult.


Your code isn't starting at the top of the function. What you are
seeing is another call thats just been made.

As a test, in your timer function just keep creating new forms, dont
close them. Each time Call showdialog, then show a message box.
If you wait untill 5 forms are all showing at the same time, you won't
have seen any message boxs. As you close all of them, you will see 5
message boxs.

is this?

It works the second time through because you designed your state
machine well. The problem is your code is designed to run in a loop,
and the timer event that your using is close to a loop, but it's not.

would this work for you instead?

private EventHandler SomeCallback;

protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);

this.SomeCallback = new EventHandler(this.SomeEventHandler);
new System.Threading.Thread(new
System.Threading.ThreadStart(SomeThread)).Start();
}

public void SomeThread()
{
while ( true )
{
string status = this.MyController.GetApplicantStatus();

if( status == "H" ) //Hold
{
if(this.pause == null)
{
this.BeginInvoke(SomeCallback);
}
}
else if( status == "T" ) //Terminated
{
if(this.pause != null)
pause.Close();

this.terminateTimer.Stop();
this.MyController.TerminateSession();
}
else
{
if(this.pause != null)
{
pause.Close();
pause.Dispose();
}
}
string x="asdfasdf";

System.Threading.Thread.Sleep(5000); //TerminateTimer.Interval
}
}

private void SomeEventHandler(object s, System.EventArgs e)
{
pause = new Pause();
pause.ShowDialog();
}

Kind Regards,
Jerron
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top