Executing a program while displaying a model window

E

Eric Paul

I have searched in vain for what seems like something that should be
simple to accomplish.

I have a Windows application written in C# that scans a driver's
license. While it's scanning I want to display a "Scanning..."
progress bar window until the scanning is complete or the user clicks
cancel.
All is fine as long as I use "form.visible" to display the window with
the progress bar.
I use another thread to display the window and then I kill the thread
when the scanning completes.
The problem is that I want this "progress bar" window to be modal--not
modeless. If I use the "form.showDialog()" all processing stops in the
new thread--the progress bar never updates until the process is
complete.

Is there a way to use a modal window and still continue program
execution?

I have searched and found some references to using "Application.Run()"
and "Form.Invoke" but they're not really very clear on how to
accomplish this. It seems like this problem should have been solved
before since many applications have modal "progress bar" windows but I
can't find any good examples. Here is a sampling of my current code:


Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();

myScan.Scan();
Byte[] byteBLOBData = new Byte[0];
FileStream fs = new FileStream(ConfigurationSettings.AppSettings["ImageFilename"],
FileMode.Open, FileAccess.Read);
photoBox1.Image= Image.FromStream(fs);
fs.Close();
myScan.ExtractOCRData();
t.Abort();
myScan.ExtractFaceImage();
myScan.ExtractSignature();

if (myScan.ScannerError == false)
{
txtNameOnCard_OCR.Text = myScan.NameOnCard;
txtFirstName_OCR.Text = myScan.FirstName;
txtMiddleName_OCR.Text = myScan.MiddleName;
txtLastName_OCR.Text = myScan.LastName;
txtSuffixName_OCR.Text = myScan.SuffixName;
txtAddress_OCR.Text = myScan.Address;
txtCity_OCR.Text = myScan.City;
txtState_OCR.Text = myScan.State;
txtZip_OCR.Text = myScan.Zip;
txtDOB_OCR.Text = myScan.DOB;
txtIssue_OCR.Text = myScan.Issue;
txtExpires_OCR.Text = myScan.Expires;
txtID_OCR.Text = myScan.ID;
txtAccuracy_OCR.Text = myScan.Accuracy + "";
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}


public static void ThreadProc()
{
// construct a new progress dialog
frmProgress myProgressDialog = new frmProgress();

myProgressDialog.progressBar1.Minimum = 0;
myProgressDialog.progressBar1.Maximum = 9;
myProgressDialog.progressBar1.Step = 1;
myProgressDialog.progressBar1.Value = 0;

myProgressDialog.FormBorderStyle = FormBorderStyle.FixedDialog;
myProgressDialog.StartPosition = FormStartPosition.CenterScreen;
myProgressDialog.Visible = true;
myProgressDialog.Update();
myProgressDialog.Refresh();
myProgressDialog.CancelButton = myProgressDialog.btnCancel;

while ( myProgressDialog.progressBar1.Value <
myProgressDialog.progressBar1.Maximum )
{
myProgressDialog.progressBar1.Value++;
System.Threading.Thread.Sleep(1000);
myProgressDialog.Update();
myProgressDialog.Refresh();
}

//System.Threading.Thread.Sleep(2500);
myProgressDialog.Visible = false;
}

Any and all suggestions are most welcome.

Thanks,

Eric
 
N

Nicholas Paldino [.NET/C# MVP]

Eric,

You will need to do the following. First, your dialog will be what
controls the scanning (at least, the thread that is kicked off to process
the scanning). The dialog will be created, and then shown modally.

When the dialog is shown, it will kick off another thread, this thread
will run the code that performs the scanning.

When you want to update the progress, you will call the Invoke method on
the progress bar, passing a delegate, as well as the parameters (if any),
that are required by the method that the delegate represents.

Now, what your delegate represents is important. You need a method that
is going to update the progress bar correctly. For this, I would imagine
you need to have the current value. This would be the parameter to your
method. In the method, update the progress bar as you would normally. Once
you have that, you can create a delegate type with the same signature and
then use that in the call to Invoke.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Eric Paul said:
I have searched in vain for what seems like something that should be
simple to accomplish.

I have a Windows application written in C# that scans a driver's
license. While it's scanning I want to display a "Scanning..."
progress bar window until the scanning is complete or the user clicks
cancel.
All is fine as long as I use "form.visible" to display the window with
the progress bar.
I use another thread to display the window and then I kill the thread
when the scanning completes.
The problem is that I want this "progress bar" window to be modal--not
modeless. If I use the "form.showDialog()" all processing stops in the
new thread--the progress bar never updates until the process is
complete.

Is there a way to use a modal window and still continue program
execution?

I have searched and found some references to using "Application.Run()"
and "Form.Invoke" but they're not really very clear on how to
accomplish this. It seems like this problem should have been solved
before since many applications have modal "progress bar" windows but I
can't find any good examples. Here is a sampling of my current code:


Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();

myScan.Scan();
Byte[] byteBLOBData = new Byte[0];
FileStream fs = new FileStream(ConfigurationSettings.AppSettings["ImageFilename"],
FileMode.Open, FileAccess.Read);
photoBox1.Image= Image.FromStream(fs);
fs.Close();
myScan.ExtractOCRData();
t.Abort();
myScan.ExtractFaceImage();
myScan.ExtractSignature();

if (myScan.ScannerError == false)
{
txtNameOnCard_OCR.Text = myScan.NameOnCard;
txtFirstName_OCR.Text = myScan.FirstName;
txtMiddleName_OCR.Text = myScan.MiddleName;
txtLastName_OCR.Text = myScan.LastName;
txtSuffixName_OCR.Text = myScan.SuffixName;
txtAddress_OCR.Text = myScan.Address;
txtCity_OCR.Text = myScan.City;
txtState_OCR.Text = myScan.State;
txtZip_OCR.Text = myScan.Zip;
txtDOB_OCR.Text = myScan.DOB;
txtIssue_OCR.Text = myScan.Issue;
txtExpires_OCR.Text = myScan.Expires;
txtID_OCR.Text = myScan.ID;
txtAccuracy_OCR.Text = myScan.Accuracy + "";
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}


public static void ThreadProc()
{
// construct a new progress dialog
frmProgress myProgressDialog = new frmProgress();

myProgressDialog.progressBar1.Minimum = 0;
myProgressDialog.progressBar1.Maximum = 9;
myProgressDialog.progressBar1.Step = 1;
myProgressDialog.progressBar1.Value = 0;

myProgressDialog.FormBorderStyle = FormBorderStyle.FixedDialog;
myProgressDialog.StartPosition = FormStartPosition.CenterScreen;
myProgressDialog.Visible = true;
myProgressDialog.Update();
myProgressDialog.Refresh();
myProgressDialog.CancelButton = myProgressDialog.btnCancel;

while ( myProgressDialog.progressBar1.Value <
myProgressDialog.progressBar1.Maximum )
{
myProgressDialog.progressBar1.Value++;
System.Threading.Thread.Sleep(1000);
myProgressDialog.Update();
myProgressDialog.Refresh();
}

//System.Threading.Thread.Sleep(2500);
myProgressDialog.Visible = false;
}

Any and all suggestions are most welcome.

Thanks,

Eric
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi Erick,

I do a similar thing, What I do is that the main thread is used for the UI,
I display the form with ShowDialog() and is inside this form where I create
the working thread where I perforn the works:

I do something little different though, I'm copying a group of files from
the desktop to a PocketPC so my working thread perform the copy and each
time a file is copied the progress bar is updated with the name of the file
just copied. but other than that it does what you are trying to do.

Below you will find the code I use:

//Open the form ( from main form )
private void button2_Click(object sender, System.EventArgs e)

{

new ExportImages().ShowDialog();


}

In ExportImages form:
public delegate void ProcessedFileHandler( ); // I use this delegate to send
an event from the working thread to the UI thread.

//Create the thread and init the progress bar

private void ImportImages_Load(object sender, System.EventArgs e)

{

this.files = Directory.GetFiles( Config.ExportImageDirectory);

this.progressBar1.Minimum = 0;

this.progressBar1.Maximum = files.Length;

procfilehandler = new ProcessedFileHandler( this.UpdateProgressBar);

//Start the thread

this.workingThread = new Thread( new ThreadStart( this.ExportImage ));

this.workingThread.Start();

}


//The working thread method., take a look how the event is invoked on the
thread that the control belong to:
void ExportImage( )
{
foreach(string imageURL in files)
{
this.currentpos++;
this.currentfile = Path.GetFileName(imageURL);

//Update the interface
this.progressBar1.Invoke( procfilehandler, null);

//Use RAPI to copy the file to the PPC
rapi.CopyFileToDevice( imageUrl, targeurl , true);
}
//All we need is a control in the main thread to execute a method on the
main thread.
this.progressBar1.Invoke( new ProcessedFileHandler( this.Done), null);
}

//Here is the Handler of the Update Progress bar.
void UpdateProgressBar( )
{
this.progressBar1.Value++;
FileNameLBL.Text = currentfile;
currentLBL.Text = currentpos.ToString();
}


Hope this help,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

Eric Paul said:
I have searched in vain for what seems like something that should be
simple to accomplish.

I have a Windows application written in C# that scans a driver's
license. While it's scanning I want to display a "Scanning..."
progress bar window until the scanning is complete or the user clicks
cancel.
All is fine as long as I use "form.visible" to display the window with
the progress bar.
I use another thread to display the window and then I kill the thread
when the scanning completes.
The problem is that I want this "progress bar" window to be modal--not
modeless. If I use the "form.showDialog()" all processing stops in the
new thread--the progress bar never updates until the process is
complete.

Is there a way to use a modal window and still continue program
execution?

I have searched and found some references to using "Application.Run()"
and "Form.Invoke" but they're not really very clear on how to
accomplish this. It seems like this problem should have been solved
before since many applications have modal "progress bar" windows but I
can't find any good examples. Here is a sampling of my current code:


Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();

myScan.Scan();
Byte[] byteBLOBData = new Byte[0];
FileStream fs = new FileStream(ConfigurationSettings.AppSettings["ImageFilename"],
FileMode.Open, FileAccess.Read);
photoBox1.Image= Image.FromStream(fs);
fs.Close();
myScan.ExtractOCRData();
t.Abort();
myScan.ExtractFaceImage();
myScan.ExtractSignature();

if (myScan.ScannerError == false)
{
txtNameOnCard_OCR.Text = myScan.NameOnCard;
txtFirstName_OCR.Text = myScan.FirstName;
txtMiddleName_OCR.Text = myScan.MiddleName;
txtLastName_OCR.Text = myScan.LastName;
txtSuffixName_OCR.Text = myScan.SuffixName;
txtAddress_OCR.Text = myScan.Address;
txtCity_OCR.Text = myScan.City;
txtState_OCR.Text = myScan.State;
txtZip_OCR.Text = myScan.Zip;
txtDOB_OCR.Text = myScan.DOB;
txtIssue_OCR.Text = myScan.Issue;
txtExpires_OCR.Text = myScan.Expires;
txtID_OCR.Text = myScan.ID;
txtAccuracy_OCR.Text = myScan.Accuracy + "";
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}


public static void ThreadProc()
{
// construct a new progress dialog
frmProgress myProgressDialog = new frmProgress();

myProgressDialog.progressBar1.Minimum = 0;
myProgressDialog.progressBar1.Maximum = 9;
myProgressDialog.progressBar1.Step = 1;
myProgressDialog.progressBar1.Value = 0;

myProgressDialog.FormBorderStyle = FormBorderStyle.FixedDialog;
myProgressDialog.StartPosition = FormStartPosition.CenterScreen;
myProgressDialog.Visible = true;
myProgressDialog.Update();
myProgressDialog.Refresh();
myProgressDialog.CancelButton = myProgressDialog.btnCancel;

while ( myProgressDialog.progressBar1.Value <
myProgressDialog.progressBar1.Maximum )
{
myProgressDialog.progressBar1.Value++;
System.Threading.Thread.Sleep(1000);
myProgressDialog.Update();
myProgressDialog.Refresh();
}

//System.Threading.Thread.Sleep(2500);
myProgressDialog.Visible = false;
}

Any and all suggestions are most welcome.

Thanks,

Eric
 
E

Eric Paul

Ignacio Machin \( .NET/ C# MVP \) said:
Hi Erick,

....

}


Hope this help,

First, thank you both for your prompt replies.

OK... I hate to be so dense, but I'm still not getting it quite right.
Based on your code example I have changed my code. (The Code Follows)
My goal seemed simple when I started this and I seem to be having a
major brain lock right now--please excuse the DUH factor.
The method myScan.Scan() calls to another DLL which starts the
scanning process during the scanning process I would like to display a
modal dialog with a progress bar. The only real method I have to judge
how long the scan takes is time--the time is consistently 9 to 10
seconds to complete the scan. When the scan is compelte another method
performs OCR and gets the Name Address, etc from the Driver's license
and sends it back to the main form.
Like your example the button that kicks the process off creates the
frmProgrss window as a modal dialog--the code below is in the Progress
Window Form (frmProgrss).
Do I need yet another thread to kick off scanning? It still seems to
do all of its updating at the end. I.E. no progress than all progress
then the scan.
Once again any advice you can offer would be greatly appreciated.


public delegate void ProgressHandler();

private void frmProgress_Load(object sender, System.EventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 9;
progressBar1.Step = 1;
progressBar1.Value = 0;

ProgressHandler progresshandler = new
ProgressHandler(this.UpdateProgressBar);

Thread t = new Thread(new ThreadStart(DoScan));
t.Start();
this.Update();
this.Refresh();

while ( progressBar1.Value < progressBar1.Maximum )
{
this.progressBar1.Invoke( progresshandler, null);
System.Threading.Thread.Sleep(1000);
this.Update();
this.Refresh();
}

// t.Abort();
// this.Close();
}

public static void DoScan()
{
frmMain myMainForm = new frmMain();
frmProgress myProgressForm = new frmProgress();
Scanner myScan = new Scanner();

myScan.CheckTray();
if (myScan.ScannerError == true)
{
//myProgressForm.Close();
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}
else
{
myScan.ImageFileName = "License.bmp";
myScan.SigFileName = "Sig.bmp";
myScan.FaceFileName = "Face.bmp";
if (myMainForm.chkAutoDetectState.Checked == true)
{
myScan.AutoDetectState = true;
}
else
{
myScan.AutoDetectState = false;
myScan.StateName =
myMainForm.cboStateList.Items[myMainForm.cboStateList.SelectedIndex].ToString();
}

if (myScan.ScannerError == false)
{
myMainForm.photoBox1.Image = null;

//delete any existing scanned image files
if(File.Exists("C:\License.bmp"))
{
File.Delete("C:\License.bmp");
}
if(File.Exists("C:\Face.bmp"))
{
File.Delete("C:\Face.bmp");
}
if(File.Exists("C:\Sig.bmp"))
{
File.Delete("C:\Sig.bmp");
}

myScan.Scan();

Byte[] byteBLOBData = new Byte[0];
FileStream fs = new FileStream(C:\License.bmp, FileMode.Open,
FileAccess.Read);
myMainForm.photoBox1.Image= Image.FromStream(fs);
fs.Close();

myScan.ExtractOCRData();
myScan.ExtractFaceImage();
myScan.ExtractSignature();

if (myScan.ScannerError == false)
{
myMainForm.txtNameOnCard_OCR.Text = myScan.NameOnCard;
myMainForm.txtFirstName_OCR.Text = myScan.FirstName;
myMainForm.txtMiddleName_OCR.Text = myScan.MiddleName;
myMainForm.txtLastName_OCR.Text = myScan.LastName;
myMainForm.txtSuffixName_OCR.Text = myScan.SuffixName;
myMainForm.txtAddress_OCR.Text = myScan.Address;
myMainForm.txtCity_OCR.Text = myScan.City;
myMainForm.txtState_OCR.Text = myScan.State;
myMainForm.txtZip_OCR.Text = myScan.Zip;
myMainForm.txtDOB_OCR.Text = myScan.DOB;
myMainForm.txtIssue_OCR.Text = myScan.Issue;
myMainForm.txtExpires_OCR.Text = myScan.Expires;
myMainForm.txtID_OCR.Text = myScan.ID;
myMainForm.txtAccuracy_OCR.Text = myScan.Accuracy + "";
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}
myProgressForm.progressBar1.Invoke(new
ProgressHandler(myProgressForm.Close), null);
}

}
private void UpdateProgressBar( )
{
this.progressBar1.Value++;
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi Eric,

From what I understand you have a situation a little different that the one
I had, your working thread does not send events to the UI ( at least on a
regular base anyway ).
Therefore I would change to one of these two options:

Option 1:

1- Use a flag that is set on the working thread to indicate that it finish
it.
2- Use a timer on the UI thread, this timer check the flag, if it's not set
it update the progress bar.
if the flag is set then the process is finished and it update the UI
according.

Option 2:
1- A similar approach to my first post, use a delegate to invoke the "Work
Done" event to the main thread.
2- Use a timer and update the progress bar independly of the working
thread.


A modified a little the code I sent you before for the second approach:


System.Windows.Form.Timer timer;

private void ImportImages_Load(object sender, System.EventArgs e)
{
timer = new Timer;
//set the timer properties ( not shown ) it will call UpdateProgressBar
method

//Start the thread
this.workingThread = new Thread( new ThreadStart( this.ExportImage ));
this.workingThread.Start();
}


void ExportImage( )
{

//Do your processing here

this.progressBar1.Invoke( new ProcessedFileHandler( this.Done), null);
}

// ******************
// The events handlers;
// ******************
void UpdateProgressBar( object o , EventArgs e )
{
if ( progressBar1.Value == progressBar.Max )
progressBar.Value = progressBar.Min;
else
progressBar.Value ++;

}
void Done()
{
timer1.enabled = false;
// Do the cleaning and save the needed data
this.Close();
}


Hope this help,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

Eric Paul said:
"Ignacio Machin \( .NET/ C# MVP \)" <ignacio.machin AT dot.state.fl.us>
wrote in message news: said:
Hi Erick,

...

}


Hope this help,

First, thank you both for your prompt replies.

OK... I hate to be so dense, but I'm still not getting it quite right.
Based on your code example I have changed my code. (The Code Follows)
My goal seemed simple when I started this and I seem to be having a
major brain lock right now--please excuse the DUH factor.
The method myScan.Scan() calls to another DLL which starts the
scanning process during the scanning process I would like to display a
modal dialog with a progress bar. The only real method I have to judge
how long the scan takes is time--the time is consistently 9 to 10
seconds to complete the scan. When the scan is compelte another method
performs OCR and gets the Name Address, etc from the Driver's license
and sends it back to the main form.
Like your example the button that kicks the process off creates the
frmProgrss window as a modal dialog--the code below is in the Progress
Window Form (frmProgrss).
Do I need yet another thread to kick off scanning? It still seems to
do all of its updating at the end. I.E. no progress than all progress
then the scan.
Once again any advice you can offer would be greatly appreciated.


public delegate void ProgressHandler();

private void frmProgress_Load(object sender, System.EventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 9;
progressBar1.Step = 1;
progressBar1.Value = 0;

ProgressHandler progresshandler = new
ProgressHandler(this.UpdateProgressBar);

Thread t = new Thread(new ThreadStart(DoScan));
t.Start();
this.Update();
this.Refresh();

while ( progressBar1.Value < progressBar1.Maximum )
{
this.progressBar1.Invoke( progresshandler, null);
System.Threading.Thread.Sleep(1000);
this.Update();
this.Refresh();
}

// t.Abort();
// this.Close();
}

public static void DoScan()
{
frmMain myMainForm = new frmMain();
frmProgress myProgressForm = new frmProgress();
Scanner myScan = new Scanner();

myScan.CheckTray();
if (myScan.ScannerError == true)
{
//myProgressForm.Close();
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}
else
{
myScan.ImageFileName = "License.bmp";
myScan.SigFileName = "Sig.bmp";
myScan.FaceFileName = "Face.bmp";
if (myMainForm.chkAutoDetectState.Checked == true)
{
myScan.AutoDetectState = true;
}
else
{
myScan.AutoDetectState = false;
myScan.StateName =
myMainForm.cboStateList.Items[myMainForm.cboStateList.SelectedIndex].ToStrin
g();
}

if (myScan.ScannerError == false)
{
myMainForm.photoBox1.Image = null;

//delete any existing scanned image files
if(File.Exists("C:\License.bmp"))
{
File.Delete("C:\License.bmp");
}
if(File.Exists("C:\Face.bmp"))
{
File.Delete("C:\Face.bmp");
}
if(File.Exists("C:\Sig.bmp"))
{
File.Delete("C:\Sig.bmp");
}

myScan.Scan();

Byte[] byteBLOBData = new Byte[0];
FileStream fs = new FileStream(C:\License.bmp, FileMode.Open,
FileAccess.Read);
myMainForm.photoBox1.Image= Image.FromStream(fs);
fs.Close();

myScan.ExtractOCRData();
myScan.ExtractFaceImage();
myScan.ExtractSignature();

if (myScan.ScannerError == false)
{
myMainForm.txtNameOnCard_OCR.Text = myScan.NameOnCard;
myMainForm.txtFirstName_OCR.Text = myScan.FirstName;
myMainForm.txtMiddleName_OCR.Text = myScan.MiddleName;
myMainForm.txtLastName_OCR.Text = myScan.LastName;
myMainForm.txtSuffixName_OCR.Text = myScan.SuffixName;
myMainForm.txtAddress_OCR.Text = myScan.Address;
myMainForm.txtCity_OCR.Text = myScan.City;
myMainForm.txtState_OCR.Text = myScan.State;
myMainForm.txtZip_OCR.Text = myScan.Zip;
myMainForm.txtDOB_OCR.Text = myScan.DOB;
myMainForm.txtIssue_OCR.Text = myScan.Issue;
myMainForm.txtExpires_OCR.Text = myScan.Expires;
myMainForm.txtID_OCR.Text = myScan.ID;
myMainForm.txtAccuracy_OCR.Text = myScan.Accuracy + "";
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}
}
else
{
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
return;
}
myProgressForm.progressBar1.Invoke(new
ProgressHandler(myProgressForm.Close), null);
}

}
private void UpdateProgressBar( )
{
this.progressBar1.Value++;
}
 
E

Eric Paul

Ignacio,

Thanks so much for your help. I'm afraid I'm still missing some piece
to the puzzle here and I apologize for being so dim.
I now have a better understanding of Delegates (I think) because of
your advice here and a bunch of reading online and going through
examples. I think the delegate thing is what I'm having a tough time
with—but as I understand it now the delegate is what allows me to call
methods from my original thread and execute them from my new
thread--right?
So basically I have everything working now except it appears that I'm
not able to kill off my original thread. Basically the line:

this.progressBar1.Invoke(new ProgressHandler(this.done),null);

is returning a System.NullReference exception. Which I think is
telling me that since it was never instantiated in the original thread
there's nothing to do?? Or maybe refrence to the fact that Timer1 and
workingThread (which are called in the method) don't exist in the
current thread?
If I comment the invoke line out pushing the scan button works
flawlessly the first time, but fails the second time because the
"myScan" object has already been initialized (the dll I'm using won't
let it be initialized twice). The reason the object still exists is
because I never really terminated the thread—I think. What follows is
the code that works—it performs a scan and posts the collected data
back to the main form, but never really uses the delegate. I did try
declaring the delegate like:

public delegate void ProgressHandler();
....
private void frmProgress_Load(object sender, System.EventArgs e)
{
....
ProgressHandler procfilehandler = new
ProgressHandler(this.UpdateProgressBar);
....
}
in the frm_Load method but It keeps telling me that it "does not match
the delegate" which I don't understand—the method return type is void
with no parameters the same as the delegate.
I think I'm getting close but I just can't seem to get the delegate
thing working—here is the latest and greatest code. I hope you'll take
pity on me, look it over, and tell me where I went wrong.
Thanks.

....

public delegate void ProgressHandler();
public Thread workingThread;

private void frmProgress_Load(object sender, System.EventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 25;
progressBar1.Step = 1;
progressBar1.Value = 0;

//Start the thread
workingThread = new Thread( new ThreadStart( DoScan ));
workingThread.Start();

//ProgressHandler procfilehandler = new
ProgressHandler(this.UpdateProgressBar);

System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
timer1.Interval = 1000;
timer1.Enabled = true;
timer1.Tick += new EventHandler(this.UpdateProgressBar);
timer1.Start();
}

public void DoScan()
{
frmMain myMainForm = new frmMain();
Scanner myScan = new Scanner();

myScan.CheckTray();
if (myScan.ScannerError == true)
{
this.DialogResult = DialogResult.Cancel;
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
}
else
{
myScan.ImageFileName = ImageFilename;
myScan.SigFileName = SigFilename;
myScan.FaceFileName = FaceFilename;

if (myMainForm.chkAutoDetectState.Checked == true)
{
myScan.AutoDetectState = true;
}
else
{
myScan.AutoDetectState = false;
myScan.StateName =
myMainForm.cboStateList.Items[myMainForm.cboStateList.SelectedIndex].ToString();
}

if (myScan.ScannerError == false)
{
myScan.Scan();

Byte[] byteBLOBData = new Byte[0];
FileStream fs = new FileStream(ImageFilename, FileMode.Open,
FileAccess.Read);
myMainForm.photoBox1.Image= Image.FromStream(fs);
fs.Close();

myScan.ExtractOCRData();
myScan.ExtractFaceImage();
myScan.ExtractSignature();



if (myScan.ScannerError == false)
{
myNameOnCard = myScan.NameOnCard;
myFirstName = myScan.FirstName;
myMiddleName = myScan.MiddleName;
myLastName = myScan.LastName;
mySuffixName = myScan.SuffixName;
myAddress = myScan.Address;
myCity = myScan.City;
myState = myScan.State;
myZip = myScan.Zip;
myDOB = myScan.DOB;
myIssue = myScan.Issue;
myExpires = myScan.Expires;
myID = myScan.ID;
myAccuracy = myScan.Accuracy + "";

myScan = null;

this.DialogResult = DialogResult.OK;
//this.progressBar1.Invoke(new ProgressHandler(this.done),null);
}
else
{
this.DialogResult = DialogResult.Cancel;
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
}
}
else
{
this.DialogResult = DialogResult.Cancel;
MessageBox.Show(myScan.ScannerErrorMessage);
myScan.ScannerError = false;
}
}

}

//this method return an error when executed in the "doscan" thread
directly
private void done()
{
this.timer1.Enabled = false;
this.timer1.Stop();
this.workingThread.Abort();
}

private void UpdateProgressBar( object o , EventArgs e )
{
if ( this.progressBar1.Value == progressBar1.Maximum)
{
this.progressBar1.Value = progressBar1.Minimum;
}
else
{
this.progressBar1.Value++;
}
}
 
Top