Delegates and Worker Threads, Episode II

J

Joey Powell

Re: Original post = Windows forms - how do I get them to render/update
properly? from August 22.

Okay I am making some progress with being able to use delegates to run
my shelled processes on worker threads. Yes I have gotten it to work,
kind-of - that is I have gotten the shelled processes off of the UI
thread (I think?). But the UI still is not updating properly! Still I
have white boxes for forms, label text that does not update, and extra
windows in the taskbar.

Also I am not sure about the shelled apps themselves - they do not
appear to be multi-threaded because they essentially "take over" the
system - it does not respond at all - for short periods of time.

Anyways something is still preventing the UI in my app from updating
properly. What in the world am I doing wrong here?

Below is some code from the app. I have shortened a lot of stuff to
make it more readable...

....

//part I - declare delegates
public class _SomeClass : System.Windows.Forms.Form
{
private delegate bool _CCDelegate();
private delegate bool _URTDelegate();

[other code below...]

....

//part II - instantiate and invoke

[...other code above]

//check communications
this.lblStatus.Text = "Status: Checking communications, please
wait...";
_CCDelegate CCDelegate = new _CCDelegate(CC);
IAsyncResult CCResult = CCDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(CCDelegate.EndInvoke(CCResult)))
{
this.lblStatus.Text = "Status: Check failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Check was successful.";

//Upload report totals
this.lblStatus.Text = "Status: Uploading report totals, please
wait...";
_URTDelegate URTDelegate = new _URTDelegate(URT);
IAsyncResult URTResult = URTDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(URTDelegate.EndInvoke(URTResult)))
{
this.lblStatus.Text = "Status: Upload of report totals failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Upload of report totals was
successful.";

[other code below...]

....

//part III - functions

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool CC()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool URT()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

....

Okay now I understand that I am using asynchonous processing here, yet
I am blocking with EndInvoke...but I have to make this stuff process
synchonously. It is very important that one process finishes before
the next one begins. If there is a better way then will someone please
post the code?

At this point all I need is:

1. The ability to get processes off of the UI thread so that the UI
continues to update properly.

2. The ability to run those processes syncronously.

I would really appreciate any help from any of you as I really want to
be able to make this work.

Thanks.
 
E

EMonaco

Joey,

When you say
[...code to launch task on Process class goes here...]

in your delegates, do you mean you are actually launching a process and
perhaps monitoring it, via System.Diagnostics.Process? If so, you can start
a process, set its .ExitCode += new EventHandler(CallbackFuncHere); and then
set its .EnableRaisingEvents = true; Thus you will get a callback when the
process completes (wheter good or bad) from that callback you can chain more
process starts with new callback handlers to "serialize" the whole flow.

My guess is that your delegates take some time to execute. When you do the
following:
IAsyncResult CCResult = CCDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(CCDelegate.EndInvoke(CCResult)))

My theory is that these guys:

all do their magic via a message posted to the main thread. But before you
relinquish program control (to the internal message loop) you hit:
if(!(CCDelegate.EndInvoke(CCResult)))

Which blocks... And viola, its just like you did a plain old invoke!

If you are not using System.Diagnostics.Process to actually create other
processes in the delegates, perhaps you should pass the BeginInvoke a
"callback" delegate. From within this callback you do what amounts to a
non-blocking EndInvoke() and proceed to issue the next BeginInvoke with a
new callback, and so on till everything is serialized to your liking but the
main thread is basically sitting around in its message loop!


Hope this helps.

Regards,
Erin.
 
J

Joey Powell

Guys, I have read all of the links. I have tried the suggested
options, though I am not sure about the code one would use to
implement either. I have successfully created and used delegates (as
shown in the posted code). However, the UI ***still does not
update***. I have been stuck on this for a few months now. Can anyone
out there offer a simple solution to make this work? Specifically, how
could one modify the posted code to make it update the UI properly? I
am running out of options here...I guess I don't "get it". This
continues to be extremely frustrating, but I am not going to give
up...

Thanks,
JP

Joe Mayo said:
Hi Joey,

Here are some articles on threading that should help you get up to speed.

http://www.windowsforms.net/Default.aspx?tabindex=3&tabid=40#Threading

Remember to use Control.Invoke/BeginInvoke, to call a method on your main UI
thread that updates your UI. Also, if you use BeginInvoke, be sure to call
EndInvoke to avoid a memory leak.

Also, check out the asynchronous delegate pattern that uses the
AsyncCallback parameter of BeginInvoke. I may be mistaken, but I think part
of your UI updating problem may be that you are calling EndInvoke in the
same method as BeginInvoke and blocking on your main UI thread. Here's a
reference to the async delegate patterns:

http://msdn.microsoft.com/library/d...ml/cpconasynchronousdesignpatternoverview.asp

Look at the example that says "Supply the callback delegate when beginning
the asynchronous call."

Joe
--
http://www.csharp-station.com


Joey Powell said:
Re: Original post = Windows forms - how do I get them to render/update
properly? from August 22.

Okay I am making some progress with being able to use delegates to run
my shelled processes on worker threads. Yes I have gotten it to work,
kind-of - that is I have gotten the shelled processes off of the UI
thread (I think?). But the UI still is not updating properly! Still I
have white boxes for forms, label text that does not update, and extra
windows in the taskbar.

Also I am not sure about the shelled apps themselves - they do not
appear to be multi-threaded because they essentially "take over" the
system - it does not respond at all - for short periods of time.

Anyways something is still preventing the UI in my app from updating
properly. What in the world am I doing wrong here?

Below is some code from the app. I have shortened a lot of stuff to
make it more readable...

...

//part I - declare delegates
public class _SomeClass : System.Windows.Forms.Form
{
private delegate bool _CCDelegate();
private delegate bool _URTDelegate();

[other code below...]

...

//part II - instantiate and invoke

[...other code above]

//check communications
this.lblStatus.Text = "Status: Checking communications, please
wait...";
_CCDelegate CCDelegate = new _CCDelegate(CC);
IAsyncResult CCResult = CCDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(CCDelegate.EndInvoke(CCResult)))
{
this.lblStatus.Text = "Status: Check failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Check was successful.";

//Upload report totals
this.lblStatus.Text = "Status: Uploading report totals, please
wait...";
_URTDelegate URTDelegate = new _URTDelegate(URT);
IAsyncResult URTResult = URTDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(URTDelegate.EndInvoke(URTResult)))
{
this.lblStatus.Text = "Status: Upload of report totals failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Upload of report totals was
successful.";

[other code below...]

...

//part III - functions

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool CC()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool URT()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

...

Okay now I understand that I am using asynchonous processing here, yet
I am blocking with EndInvoke...but I have to make this stuff process
synchonously. It is very important that one process finishes before
the next one begins. If there is a better way then will someone please
post the code?

At this point all I need is:

1. The ability to get processes off of the UI thread so that the UI
continues to update properly.

2. The ability to run those processes syncronously.

I would really appreciate any help from any of you as I really want to
be able to make this work.

Thanks.
 
M

Michael Mayer

Can you provide a short and complete prorgram - that compiles - and then
I'll have a look at it (and I'm bet some other people will as well). It's
sometimes hard to piece together exactly what is happenning form small code
fragments (especially when >> is in front of every line).

See Jon Skeet's page on short but complete:
http://www.pobox.com/~skeet/csharp/complete.html

--
Mike Mayer
http://www.mag37.com/csharp/
(e-mail address removed)


Joey Powell said:
Guys, I have read all of the links. I have tried the suggested
options, though I am not sure about the code one would use to
implement either. I have successfully created and used delegates (as
shown in the posted code). However, the UI ***still does not
update***. I have been stuck on this for a few months now. Can anyone
out there offer a simple solution to make this work? Specifically, how
could one modify the posted code to make it update the UI properly? I
am running out of options here...I guess I don't "get it". This
continues to be extremely frustrating, but I am not going to give
up...

Thanks,
JP

"Joe Mayo" <[email protected]> wrote in message
Hi Joey,

Here are some articles on threading that should help you get up to speed.

http://www.windowsforms.net/Default.aspx?tabindex=3&tabid=40#Threading

Remember to use Control.Invoke/BeginInvoke, to call a method on your main UI
thread that updates your UI. Also, if you use BeginInvoke, be sure to call
EndInvoke to avoid a memory leak.

Also, check out the asynchronous delegate pattern that uses the
AsyncCallback parameter of BeginInvoke. I may be mistaken, but I think part
of your UI updating problem may be that you are calling EndInvoke in the
same method as BeginInvoke and blocking on your main UI thread. Here's a
reference to the async delegate patterns:

http://msdn.microsoft.com/library/d...ml/cpconasynchronousdesignpatternoverview.asp

Look at the example that says "Supply the callback delegate when beginning
the asynchronous call."

Joe
--
http://www.csharp-station.com


Joey Powell said:
Re: Original post = Windows forms - how do I get them to render/update
properly? from August 22.

Okay I am making some progress with being able to use delegates to run
my shelled processes on worker threads. Yes I have gotten it to work,
kind-of - that is I have gotten the shelled processes off of the UI
thread (I think?). But the UI still is not updating properly! Still I
have white boxes for forms, label text that does not update, and extra
windows in the taskbar.

Also I am not sure about the shelled apps themselves - they do not
appear to be multi-threaded because they essentially "take over" the
system - it does not respond at all - for short periods of time.

Anyways something is still preventing the UI in my app from updating
properly. What in the world am I doing wrong here?

Below is some code from the app. I have shortened a lot of stuff to
make it more readable...

...

//part I - declare delegates
public class _SomeClass : System.Windows.Forms.Form
{
private delegate bool _CCDelegate();
private delegate bool _URTDelegate();

[other code below...]

...

//part II - instantiate and invoke

[...other code above]

//check communications
this.lblStatus.Text = "Status: Checking communications, please
wait...";
_CCDelegate CCDelegate = new _CCDelegate(CC);
IAsyncResult CCResult = CCDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(CCDelegate.EndInvoke(CCResult)))
{
this.lblStatus.Text = "Status: Check failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Check was successful.";

//Upload report totals
this.lblStatus.Text = "Status: Uploading report totals, please
wait...";
_URTDelegate URTDelegate = new _URTDelegate(URT);
IAsyncResult URTResult = URTDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(URTDelegate.EndInvoke(URTResult)))
{
this.lblStatus.Text = "Status: Upload of report totals failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Upload of report totals was
successful.";

[other code below...]

...

//part III - functions

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool CC()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool URT()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

...

Okay now I understand that I am using asynchonous processing here, yet
I am blocking with EndInvoke...but I have to make this stuff process
synchonously. It is very important that one process finishes before
the next one begins. If there is a better way then will someone please
post the code?

At this point all I need is:

1. The ability to get processes off of the UI thread so that the UI
continues to update properly.

2. The ability to run those processes syncronously.

I would really appreciate any help from any of you as I really want to
be able to make this work.

Thanks.
 
J

Joey Powell

Sorry, the URL was incorrect. This one is right...

http://www.goldcoinc.com/temp/POST543Report.cs_

Michael Mayer said:
Can you provide a short and complete prorgram - that compiles - and then
I'll have a look at it (and I'm bet some other people will as well). It's
sometimes hard to piece together exactly what is happenning form small code
fragments (especially when >> is in front of every line).

See Jon Skeet's page on short but complete:
http://www.pobox.com/~skeet/csharp/complete.html

--
Mike Mayer
http://www.mag37.com/csharp/
(e-mail address removed)


Joey Powell said:
Guys, I have read all of the links. I have tried the suggested
options, though I am not sure about the code one would use to
implement either. I have successfully created and used delegates (as
shown in the posted code). However, the UI ***still does not
update***. I have been stuck on this for a few months now. Can anyone
out there offer a simple solution to make this work? Specifically, how
could one modify the posted code to make it update the UI properly? I
am running out of options here...I guess I don't "get it". This
continues to be extremely frustrating, but I am not going to give
up...

Thanks,
JP

"Joe Mayo" <[email protected]> wrote in message
Hi Joey,

Here are some articles on threading that should help you get up to speed.

http://www.windowsforms.net/Default.aspx?tabindex=3&tabid=40#Threading

Remember to use Control.Invoke/BeginInvoke, to call a method on your main UI
thread that updates your UI. Also, if you use BeginInvoke, be sure to call
EndInvoke to avoid a memory leak.

Also, check out the asynchronous delegate pattern that uses the
AsyncCallback parameter of BeginInvoke. I may be mistaken, but I think part
of your UI updating problem may be that you are calling EndInvoke in the
same method as BeginInvoke and blocking on your main UI thread. Here's a
reference to the async delegate patterns:

http://msdn.microsoft.com/library/d...ml/cpconasynchronousdesignpatternoverview.asp

Look at the example that says "Supply the callback delegate when beginning
the asynchronous call."

Joe
--
http://www.csharp-station.com


Re: Original post = Windows forms - how do I get them to render/update
properly? from August 22.

Okay I am making some progress with being able to use delegates to run
my shelled processes on worker threads. Yes I have gotten it to work,
kind-of - that is I have gotten the shelled processes off of the UI
thread (I think?). But the UI still is not updating properly! Still I
have white boxes for forms, label text that does not update, and extra
windows in the taskbar.

Also I am not sure about the shelled apps themselves - they do not
appear to be multi-threaded because they essentially "take over" the
system - it does not respond at all - for short periods of time.

Anyways something is still preventing the UI in my app from updating
properly. What in the world am I doing wrong here?

Below is some code from the app. I have shortened a lot of stuff to
make it more readable...

...

//part I - declare delegates
public class _SomeClass : System.Windows.Forms.Form
{
private delegate bool _CCDelegate();
private delegate bool _URTDelegate();

[other code below...]

...

//part II - instantiate and invoke

[...other code above]

//check communications
this.lblStatus.Text = "Status: Checking communications, please
wait...";
_CCDelegate CCDelegate = new _CCDelegate(CC);
IAsyncResult CCResult = CCDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(CCDelegate.EndInvoke(CCResult)))
{
this.lblStatus.Text = "Status: Check failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Check was successful.";

//Upload report totals
this.lblStatus.Text = "Status: Uploading report totals, please
wait...";
_URTDelegate URTDelegate = new _URTDelegate(URT);
IAsyncResult URTResult = URTDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(URTDelegate.EndInvoke(URTResult)))
{
this.lblStatus.Text = "Status: Upload of report totals failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Upload of report totals was
successful.";

[other code below...]

...

//part III - functions

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool CC()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool URT()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

...

Okay now I understand that I am using asynchonous processing here, yet
I am blocking with EndInvoke...but I have to make this stuff process
synchonously. It is very important that one process finishes before
the next one begins. If there is a better way then will someone please
post the code?

At this point all I need is:

1. The ability to get processes off of the UI thread so that the UI
continues to update properly.

2. The ability to run those processes syncronously.

I would really appreciate any help from any of you as I really want to
be able to make this work.

Thanks.
 
J

Joshua Coady

Calling EndInvoke stops the asynchronous processing and blocks until the
function returns. You do not need to call EndInvoke in your class at all. If
you want notification that the process has finsihed, then pass in an
AsyncCallback to the BeginInvoke method. When the process finishes, the
callback you passed in will be called.

If you want to have a progress report at certain intervals then you have a
little more coding to do: it boils down to checking the state of the object
you are processing at a certain interval.

Hope this helps. I will try to reply later with a full example.

Josh


Joey Powell said:
Guys, I have read all of the links. I have tried the suggested
options, though I am not sure about the code one would use to
implement either. I have successfully created and used delegates (as
shown in the posted code). However, the UI ***still does not
update***. I have been stuck on this for a few months now. Can anyone
out there offer a simple solution to make this work? Specifically, how
could one modify the posted code to make it update the UI properly? I
am running out of options here...I guess I don't "get it". This
continues to be extremely frustrating, but I am not going to give
up...

Thanks,
JP

"Joe Mayo" <[email protected]> wrote in message
Hi Joey,

Here are some articles on threading that should help you get up to speed.

http://www.windowsforms.net/Default.aspx?tabindex=3&tabid=40#Threading

Remember to use Control.Invoke/BeginInvoke, to call a method on your main UI
thread that updates your UI. Also, if you use BeginInvoke, be sure to call
EndInvoke to avoid a memory leak.

Also, check out the asynchronous delegate pattern that uses the
AsyncCallback parameter of BeginInvoke. I may be mistaken, but I think part
of your UI updating problem may be that you are calling EndInvoke in the
same method as BeginInvoke and blocking on your main UI thread. Here's a
reference to the async delegate patterns:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconasynchronousdesignpatternoverview.asp
Look at the example that says "Supply the callback delegate when beginning
the asynchronous call."

Joe
--
http://www.csharp-station.com


Joey Powell said:
Re: Original post = Windows forms - how do I get them to render/update
properly? from August 22.

Okay I am making some progress with being able to use delegates to run
my shelled processes on worker threads. Yes I have gotten it to work,
kind-of - that is I have gotten the shelled processes off of the UI
thread (I think?). But the UI still is not updating properly! Still I
have white boxes for forms, label text that does not update, and extra
windows in the taskbar.

Also I am not sure about the shelled apps themselves - they do not
appear to be multi-threaded because they essentially "take over" the
system - it does not respond at all - for short periods of time.

Anyways something is still preventing the UI in my app from updating
properly. What in the world am I doing wrong here?

Below is some code from the app. I have shortened a lot of stuff to
make it more readable...

...

//part I - declare delegates
public class _SomeClass : System.Windows.Forms.Form
{
private delegate bool _CCDelegate();
private delegate bool _URTDelegate();

[other code below...]

...

//part II - instantiate and invoke

[...other code above]

//check communications
this.lblStatus.Text = "Status: Checking communications, please
wait...";
_CCDelegate CCDelegate = new _CCDelegate(CC);
IAsyncResult CCResult = CCDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(CCDelegate.EndInvoke(CCResult)))
{
this.lblStatus.Text = "Status: Check failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Check was successful.";

//Upload report totals
this.lblStatus.Text = "Status: Uploading report totals, please
wait...";
_URTDelegate URTDelegate = new _URTDelegate(URT);
IAsyncResult URTResult = URTDelegate.BeginInvoke(null, null);
this.Activate(); //try to force form to update
this.lblStatus.Refresh(); //try to force form to update
this.Refresh(); //try to force form to update
//all or part of form remains white and not updated
if(!(URTDelegate.EndInvoke(URTResult)))
{
this.lblStatus.Text = "Status: Upload of report totals failed.";
Environment.Exit(-1);
}
this.lblStatus.Text = "Status: Upload of report totals was
successful.";

[other code below...]

...

//part III - functions

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool CC()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

//this entire function should now be on a worker thread, right?
//this entire function should now be separated from the UI thread,
right?
public bool URT()
{
try
{
bool StatusFlag = false;

[...code to launch task on Process class goes here...]
//careful to include no interaction with UI

return StatusFlag;
}
catch(Exception x)
{
MessageBox.Show("FATAL ERROR - " + x.Message);
bool StatusFlag = false;
return StatusFlag;
}
}

...

Okay now I understand that I am using asynchonous processing here, yet
I am blocking with EndInvoke...but I have to make this stuff process
synchonously. It is very important that one process finishes before
the next one begins. If there is a better way then will someone please
post the code?

At this point all I need is:

1. The ability to get processes off of the UI thread so that the UI
continues to update properly.

2. The ability to run those processes syncronously.

I would really appreciate any help from any of you as I really want to
be able to make this work.

Thanks.
 
A

Andreas Huber

Joshua said:
Calling EndInvoke stops the asynchronous processing and blocks until
the function returns. You do not need to call EndInvoke in your class
at all. If you want notification that the process has finsihed, then
pass in an AsyncCallback to the BeginInvoke method. When the process
finishes, the callback you passed in will be called.

I think not calling EndInvoke (or any of the other EndXXX methods) is a bad
idea, as this will silently swallow exceptions.

Regards,

Andreas
 
W

Willy Denoyette [MVP]

Joshua Coady wrote:
|| Calling EndInvoke stops the asynchronous processing and blocks until
|| the function returns. You do not need to call EndInvoke in your
|| class at all. If you want notification that the process has
|| finsihed, then pass in an AsyncCallback to the BeginInvoke method.
|| When the process finishes, the callback you passed in will be called.
||
|| If you want to have a progress report at certain intervals then you
|| have a little more coding to do: it boils down to checking the state
|| of the object you are processing at a certain interval.
||
|| Hope this helps. I will try to reply later with a full example.
||
|| Josh
||
||

With *delegates* you are required to pair each BeginInvoke with an EndInvoke, it's only Control.BeginInvoke which doesn't require a
call to EndInvoke.

Willy.

..
 
Z

Zane Thomas [.NET/C# MVP]

Joshua,
You do not need to call EndInvoke in your class at all.

Actually, afaik, you are required to pair each BeginInvoke with an EndInvoke.
 
D

Dave

Joshua Coady said:
How is that requirement enforced? Or will bad things just happen if I dont?
(I'm interested not sarcastic: I'm working on a project that calls
BeginInvoke a lot, but seldomly calls EndInvoke.)

It isn't enforced and that's part of the problem. There are many classes
that use the EndInvoke as the equivalent of a call to Dispose, and they use
this call to cleanup. If you don't call EndInvoke then you may get memory
leaks, files not getting closed, transport connections not cleaned up, etc.

Control.Invoke is an exception to this - the .net team at this point has
made assiurances that it is safe to not call EndInvoke on a control.
 
W

Willy Denoyette [MVP]

Joshua Coady wrote:
|| How is that requirement enforced? Or will bad things just happen if
|| I dont? (I'm interested not sarcastic: I'm working on a project that
|| calls BeginInvoke a lot, but seldomly calls EndInvoke.)
||
|| For example, see the code I posted to this thread. I call begin on
|| the delegate but not end and it compiles and runs as expected.
||
|| I've included the text of that post below so you dont have to go
|| find it.
||
|| Josh
||

No it's not enforced, but it's kind of "documented" (see: Asynchronous programming overview - CAUTION Always call EndInvoke after
your asynchronous call completes.)

The main reasons why you should pair a successful BeginInvoke (or Beginxxx in general) with its EndInvoke (Endxxx) counterpart are:

1. Exceptions thrown by the asynch. method have no immediate effect, the exception object is passed to the caller at the point of
calling EndInvoke. So when your asynch. method running on a threadpool thread can possibly throw an exception you need to call
EndInvoke in order to catch.
2. The BeginInvokemethod is no managed method, it is a CLR on the fly synthesized internal using some precious native resources to
do it's job. Calling EndInvoke will release this stuff, while failing to call EndInvoke will delay this clean-up until GC and
Finalizer run.
3. Some FCL API's misbehave when Endxxx is not called after a successful call of Beginxxx (fi. BeginRead on a stream).

Willy.
 
J

Joshua Coady

To make the code I posted conform to this, all you have to do is add the endinvoke to the DoneAdding method. This may involve checking to see if it has completed yet, but that is clearly shown in the MSDN examples.

Would everyone agree that this would make the code a complete example?

Josh

|| How is that requirement enforced? Or will bad things just happen if
|| I dont? (I'm interested not sarcastic: I'm working on a project that
|| calls BeginInvoke a lot, but seldomly calls EndInvoke.)
||
|| For example, see the code I posted to this thread. I call begin on
|| the delegate but not end and it compiles and runs as expected.
||
|| I've included the text of that post below so you dont have to go
|| find it.
||
|| Josh
||

No it's not enforced, but it's kind of "documented" (see: Asynchronous programming overview - CAUTION Always call EndInvoke after
your asynchronous call completes.)

The main reasons why you should pair a successful BeginInvoke (or Beginxxx in general) with its EndInvoke (Endxxx) counterpart are:

1. Exceptions thrown by the asynch. method have no immediate effect, the exception object is passed to the caller at the point of
calling EndInvoke. So when your asynch. method running on a threadpool thread can possibly throw an exception you need to call
EndInvoke in order to catch.
2. The BeginInvokemethod is no managed method, it is a CLR on the fly synthesized internal using some precious native resources to
do it's job. Calling EndInvoke will release this stuff, while failing to call EndInvoke will delay this clean-up until GC and
Finalizer run.
3. Some FCL API's misbehave when Endxxx is not called after a successful call of Beginxxx (fi. BeginRead on a stream).

Willy.
 
W

Willy Denoyette [MVP]

Joshua Coady said:
To make the code I posted conform to this, all you have to do is add the endinvoke to the DoneAdding method. This may involve
checking to see if it has completed yet, but that is clearly shown in the MSDN examples.
Would everyone agree that this would make the code a complete example?

Josh

I do agree..

Willy.
 

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