By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,084 Members | 1,261 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,084 IT Pros & Developers. It's quick & easy.

Threading in a form...

P: n/a
Hi,

I'm trying to get my head round Async. procedure calls.

I have the following code:

delegate double GetLabourWIPDelegate(DateTime reqDate);
....
GetLabourWIPDelegate getLabourWIPDelegate = new
GetLabourWIPDelegate(GetLabourWIPOnDate);
AsyncCallback ac = new AsyncCallback(DoResult);
IAsyncResult ar = getLabourWIPDelegate.BeginInvoke(dteToDate.Value,a c,null);
....
private void DoResult(IAsyncResult ar)
{
GetLabourWIPDelegate getLabourWIPDelegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDeleg ate;
double result = getLabourWIPDelegate.EndInvoke(ar);
lblWIPLabourTo.Text = result.ToString("###,###,###,##0.00");
}

This seems to work, it starts a new thread that async. does the calculation
on the date in dteToDate ( calls GetLabourWIPOnDate), then calls DoResult on
completion which sets the label on the form to the result of the
calculation. Is is correct though?

My other question is, what happens if I want to do another calculation at
the same time. I will be calling the same calculation method, but using a
different date value, and putting the result into a different label. How
would I alter my code to do this?

Hope this makes sense, if not, please ask me to clarify anything.

Thanks,

Chris.
Sep 21 '06 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Hi Chris,

I usually pass in the delegate reference as the state argument so you can avoid the cast to AsyncResult.

You might want to encapsulate this functionality in a class. You could create a GetLabourWIPAsync method and an event that is
raised when the asynchronous operation has completed. Or, you can create BeginGetLabourWIP and EndGetLabourWIP methods. See the
links below for more info.

In the .NET 2.0 framework you can use a BackgroundWorker component instead of a delegate to provide the same functionality, along
with some extra functionality such as a progress callback and optional cancellation. BackgroundWorker can be used in the designer.

Async design pattern on MSDN:
http://msdn.microsoft.com/library/de...rnoverview.asp

Event-based async pattern on MSDN:
http://msdn2.microsoft.com/en-us/library/wewwczdw.aspx

Best practices for event-based async pattern on MSDN:
http://msdn2.microsoft.com/en-us/library/ms228974.aspx

--
Dave Sexton

"ChrisM" <ch**************@suedeyahoo.comwrote in message news:u1**************@TK2MSFTNGP04.phx.gbl...
Hi,

I'm trying to get my head round Async. procedure calls.

I have the following code:

delegate double GetLabourWIPDelegate(DateTime reqDate);
...
GetLabourWIPDelegate getLabourWIPDelegate = new GetLabourWIPDelegate(GetLabourWIPOnDate);
AsyncCallback ac = new AsyncCallback(DoResult);
IAsyncResult ar = getLabourWIPDelegate.BeginInvoke(dteToDate.Value,a c,null);
...
private void DoResult(IAsyncResult ar)
{
GetLabourWIPDelegate getLabourWIPDelegate = (GetLabourWIPDelegate)((AsyncResult)ar).AsyncDeleg ate;
double result = getLabourWIPDelegate.EndInvoke(ar);
lblWIPLabourTo.Text = result.ToString("###,###,###,##0.00");
}

This seems to work, it starts a new thread that async. does the calculation on the date in dteToDate ( calls GetLabourWIPOnDate),
then calls DoResult on completion which sets the label on the form to the result of the calculation. Is is correct though?

My other question is, what happens if I want to do another calculation at the same time. I will be calling the same calculation
method, but using a different date value, and putting the result into a different label. How would I alter my code to do this?

Hope this makes sense, if not, please ask me to clarify anything.

Thanks,

Chris.

Sep 21 '06 #2

P: n/a
Chris,

First, you cannot access controls from the callback method because it
is running on a thread other than the main UI thread. Forms and
controls must be accessed only from the main UI thread. You'll need to
use the Invoke method to marshal a delegate onto the thread hosting the
label you're wanting to modify.

To execute GetLabourWIPOnDate multiple times simultaneously just keep
calling BeginInvoke on the delegate. If you need to each one to modify
a different label when complete then just pass the label as the state
parameter.

The following example demonstrates how to do this. Hopefully it
compiles...I wrote it without testing.

void ExampleMethod()
{
GetLabourWIPDelegate delegate =
new GetLabourWIPDelegate(GetLabourWIPOnDate);

AsyncCallback callback = new AsyncCallback(DoResult);

delegate.BeginInvoke(date1, callback, label1);
delegate.BeginInvoke(date2, callback, label2);
// ...
delegate.BeginInvoke(dateN, callback, labelN);
}

void DoResult(IAsyncResult ar)
{
Label label = (Label)ar.AsyncState;
if (label.InvokeRequired)
{
// Rerun this method on the UI thread.
Delegate method = new AsyncCallback(DoResult);
object[] parameters = { ar };
label.Invoke(method, parameters);
}
else
{
// We're already on the UI thread!
GetLabourWIPDelegate delegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDeleg ate;
double result = delegate.EndInvoke(ar);
label.Text = result.ToString("###,###,###,##0.00");
}
}

Brian

ChrisM wrote:
Hi,

I'm trying to get my head round Async. procedure calls.

I have the following code:

delegate double GetLabourWIPDelegate(DateTime reqDate);
...
GetLabourWIPDelegate getLabourWIPDelegate = new
GetLabourWIPDelegate(GetLabourWIPOnDate);
AsyncCallback ac = new AsyncCallback(DoResult);
IAsyncResult ar = getLabourWIPDelegate.BeginInvoke(dteToDate.Value,a c,null);
...
private void DoResult(IAsyncResult ar)
{
GetLabourWIPDelegate getLabourWIPDelegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDeleg ate;
double result = getLabourWIPDelegate.EndInvoke(ar);
lblWIPLabourTo.Text = result.ToString("###,###,###,##0.00");
}

This seems to work, it starts a new thread that async. does the calculation
on the date in dteToDate ( calls GetLabourWIPOnDate), then calls DoResult on
completion which sets the label on the form to the result of the
calculation. Is is correct though?

My other question is, what happens if I want to do another calculation at
the same time. I will be calling the same calculation method, but using a
different date value, and putting the result into a different label. How
would I alter my code to do this?

Hope this makes sense, if not, please ask me to clarify anything.

Thanks,

Chris.
Sep 21 '06 #3

P: n/a
Brian,

Thank you very much. Exactly what I wanted to know, and some sample code as
well! Usenet answers just don't get much more helpful.
It didn't occur to me that the call back method was being called by the new
thread. Obvious now you've pointed it out, but didn't think at the time. I
can see that programming threads can be somthing of a minefield...

PS.
Only one thing wrong with your code ;-)) you called your Delegate
'delegate' which is obvioulsy a reserved word, and had the compiler whining
a little bit.

PPS

I assume that in calling the 'GetLaboutWIPOnDate' method, each thread gets
its own set of local variables etc, and is 'isolated' from all the other
threads...? I guess the only danger would be if this method referenced (or
rather actually changed) any global values, in which case there would be
some contention?

One more question (sorry!) If the method that is called by the threads,
makes a call to a static method in an object ( eg
MyObject.MyStaticMethod(someValue) ) , is this 'thread safe'? Or will it
cause problems? If it makes a difference, in my case, the static method in
question is a very simple one, it just performs a straightforward
transformation on the value passed in.

Do you have a link to a good introduction to all this stuff that would be
suitable to a newbie thread programmer like myself?

Regards,

Chris.

"Brian Gideon" <br*********@yahoo.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
Chris,

First, you cannot access controls from the callback method because it
is running on a thread other than the main UI thread. Forms and
controls must be accessed only from the main UI thread. You'll need to
use the Invoke method to marshal a delegate onto the thread hosting the
label you're wanting to modify.

To execute GetLabourWIPOnDate multiple times simultaneously just keep
calling BeginInvoke on the delegate. If you need to each one to modify
a different label when complete then just pass the label as the state
parameter.

The following example demonstrates how to do this. Hopefully it
compiles...I wrote it without testing.

void ExampleMethod()
{
GetLabourWIPDelegate delegate =
new GetLabourWIPDelegate(GetLabourWIPOnDate);

AsyncCallback callback = new AsyncCallback(DoResult);

delegate.BeginInvoke(date1, callback, label1);
delegate.BeginInvoke(date2, callback, label2);
// ...
delegate.BeginInvoke(dateN, callback, labelN);
}

void DoResult(IAsyncResult ar)
{
Label label = (Label)ar.AsyncState;
if (label.InvokeRequired)
{
// Rerun this method on the UI thread.
Delegate method = new AsyncCallback(DoResult);
object[] parameters = { ar };
label.Invoke(method, parameters);
}
else
{
// We're already on the UI thread!
GetLabourWIPDelegate delegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDeleg ate;
double result = delegate.EndInvoke(ar);
label.Text = result.ToString("###,###,###,##0.00");
}
}

Brian

ChrisM wrote:
>Hi,

I'm trying to get my head round Async. procedure calls.

I have the following code:

delegate double GetLabourWIPDelegate(DateTime reqDate);
...
GetLabourWIPDelegate getLabourWIPDelegate = new
GetLabourWIPDelegate(GetLabourWIPOnDate);
AsyncCallback ac = new AsyncCallback(DoResult);
IAsyncResult ar =
getLabourWIPDelegate.BeginInvoke(dteToDate.Value, ac,null);
...
private void DoResult(IAsyncResult ar)
{
GetLabourWIPDelegate getLabourWIPDelegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDele gate;
double result = getLabourWIPDelegate.EndInvoke(ar);
lblWIPLabourTo.Text = result.ToString("###,###,###,##0.00");
}

This seems to work, it starts a new thread that async. does the
calculation
on the date in dteToDate ( calls GetLabourWIPOnDate), then calls DoResult
on
completion which sets the label on the form to the result of the
calculation. Is is correct though?

My other question is, what happens if I want to do another calculation at
the same time. I will be calling the same calculation method, but using a
different date value, and putting the result into a different label. How
would I alter my code to do this?

Hope this makes sense, if not, please ask me to clarify anything.

Thanks,

Chris.

Sep 22 '06 #4

P: n/a
ChrisM wrote:
Brian,

Thank you very much. Exactly what I wanted to know, and some sample code as
well! Usenet answers just don't get much more helpful.
It didn't occur to me that the call back method was being called by the new
thread. Obvious now you've pointed it out, but didn't think at the time. I
can see that programming threads can be somthing of a minefield...
Well, actually asynchronous delegates run on a thread in the ThreadPool
so if you get a lot of them started then it's likely that at least a
few would be dispatched to the same thread. In other words, if you
kick off 100 of them there won't be 100 new threads created. Just to
stir the pot some more you could run delegates asynchronously using the
ThreadPool.QueueUserWorkItem method as well.

And yes, multithreaded programming is *insanely* difficult. Even
experts get tripped up frequently.
PS.
Only one thing wrong with your code ;-)) you called your Delegate
'delegate' which is obvioulsy a reserved word, and had the compiler whining
a little bit.
Oops :)
PPS

I assume that in calling the 'GetLaboutWIPOnDate' method, each thread gets
its own set of local variables etc, and is 'isolated' from all the other
threads...? I guess the only danger would be if this method referenced (or
rather actually changed) any global values, in which case there would be
some contention?
That is correct. Local variables are allocated on the stack which
means each thread will get its own copy. Like you said, be careful
when accessing class level or instance or static variables. You'll
need to synchronize access to prevent race conditions.
One more question (sorry!) If the method that is called by the threads,
makes a call to a static method in an object ( eg
MyObject.MyStaticMethod(someValue) ) , is this 'thread safe'? Or will it
cause problems? If it makes a difference, in my case, the static method in
question is a very simple one, it just performs a straightforward
transformation on the value passed in.
Since it's only modifying a parameter then yes, it's probably
thread-safe. But, if that parameter reference the same object across
all running instances of the method then it won't be. That didn't
sound like the case though.
Do you have a link to a good introduction to all this stuff that would be
suitable to a newbie thread programmer like myself?
Yes, I do. The following is probably the most cited article.

http://www.yoda.arachsys.com/csharp/threads/

But, this one appears to be well written too.

http://www.albahari.com/threading/
Regards,

Chris.
Sep 22 '06 #5

P: n/a
ChrisM wrote:
Brian,

Thank you very much. Exactly what I wanted to know, and some sample code as
well! Usenet answers just don't get much more helpful.
It didn't occur to me that the call back method was being called by the new
thread. Obvious now you've pointed it out, but didn't think at the time. I
can see that programming threads can be somthing of a minefield...
Well, actually asynchronous delegates run on a thread in the ThreadPool
so if you get a lot of them started then it's likely that at least a
few would be dispatched to the same thread. In other words, if you
kick off 100 of them there won't be 100 new threads created. Just to
stir the pot some more you could run delegates asynchronously using the
ThreadPool.QueueUserWorkItem method as well.

And yes, multithreaded programming is *insanely* difficult. Even
experts get tripped up frequently.
PS.
Only one thing wrong with your code ;-)) you called your Delegate
'delegate' which is obvioulsy a reserved word, and had the compiler whining
a little bit.
Oops :)
PPS

I assume that in calling the 'GetLaboutWIPOnDate' method, each thread gets
its own set of local variables etc, and is 'isolated' from all the other
threads...? I guess the only danger would be if this method referenced (or
rather actually changed) any global values, in which case there would be
some contention?
That is correct. Local variables are allocated on the stack which
means each thread will get its own copy. Like you said, be careful
when accessing class level or instance or static variables. You'll
need to synchronize access to prevent race conditions.
One more question (sorry!) If the method that is called by the threads,
makes a call to a static method in an object ( eg
MyObject.MyStaticMethod(someValue) ) , is this 'thread safe'? Or will it
cause problems? If it makes a difference, in my case, the static method in
question is a very simple one, it just performs a straightforward
transformation on the value passed in.
Since it's only modifying a parameter then yes, it's probably
thread-safe. But, if that parameter reference the same object across
all running instances of the method then it won't be. That didn't
sound like the case though.
Do you have a link to a good introduction to all this stuff that would be
suitable to a newbie thread programmer like myself?
Yes, I do. The following is probably the most cited article.

http://www.yoda.arachsys.com/csharp/threads/

But, this one appears to be well written too.

http://www.albahari.com/threading/
Regards,

Chris.
Sep 22 '06 #6

P: n/a
Hi Dave,

Thanks for your answer, some useful tips and ideas in there!

I'm stuck with .NET 1.1 for now, so can't use any of the new stuff in 2.0
:-(

Cheers,

Chris.

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:%2***************@TK2MSFTNGP05.phx.gbl...,
Hi Chris,

I usually pass in the delegate reference as the state argument so you can
avoid the cast to AsyncResult.

You might want to encapsulate this functionality in a class. You could
create a GetLabourWIPAsync method and an event that is raised when the
asynchronous operation has completed. Or, you can create
BeginGetLabourWIP and EndGetLabourWIP methods. See the links below for
more info.

In the .NET 2.0 framework you can use a BackgroundWorker component instead
of a delegate to provide the same functionality, along with some extra
functionality such as a progress callback and optional cancellation.
BackgroundWorker can be used in the designer.

Async design pattern on MSDN:
http://msdn.microsoft.com/library/de...rnoverview.asp

Event-based async pattern on MSDN:
http://msdn2.microsoft.com/en-us/library/wewwczdw.aspx

Best practices for event-based async pattern on MSDN:
http://msdn2.microsoft.com/en-us/library/ms228974.aspx
>
--
Dave Sexton

"ChrisM" <ch**************@suedeyahoo.comwrote in message
news:u1**************@TK2MSFTNGP04.phx.gbl...
>Hi,

I'm trying to get my head round Async. procedure calls.

I have the following code:

delegate double GetLabourWIPDelegate(DateTime reqDate);
...
GetLabourWIPDelegate getLabourWIPDelegate = new
GetLabourWIPDelegate(GetLabourWIPOnDate);
AsyncCallback ac = new AsyncCallback(DoResult);
IAsyncResult ar =
getLabourWIPDelegate.BeginInvoke(dteToDate.Value, ac,null);
...
private void DoResult(IAsyncResult ar)
{
GetLabourWIPDelegate getLabourWIPDelegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDele gate;
double result = getLabourWIPDelegate.EndInvoke(ar);
lblWIPLabourTo.Text = result.ToString("###,###,###,##0.00");
}

This seems to work, it starts a new thread that async. does the
calculation on the date in dteToDate ( calls GetLabourWIPOnDate), then
calls DoResult on completion which sets the label on the form to the
result of the calculation. Is is correct though?

My other question is, what happens if I want to do another calculation at
the same time. I will be calling the same calculation method, but using a
different date value, and putting the result into a different label. How
would I alter my code to do this?

Hope this makes sense, if not, please ask me to clarify anything.

Thanks,

Chris.


Sep 22 '06 #7

P: n/a
Hi Chris,

That's too bad. Just FYI, the async pattern and event-based async pattern info, and the recommendation to encapsulate this
functionality in a business object, is not specific to any version of the framework. Reading those articles will help you to
understand how asynchronous operations actually work in the .NET.

GL

--
Dave Sexton

"ChrisM" <ch**************@suedeyahoo.comwrote in message news:ui**************@TK2MSFTNGP05.phx.gbl...
Hi Dave,

Thanks for your answer, some useful tips and ideas in there!

I'm stuck with .NET 1.1 for now, so can't use any of the new stuff in 2.0
:-(

Cheers,

Chris.

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:%2***************@TK2MSFTNGP05.phx.gbl...,
Hi Chris,

I usually pass in the delegate reference as the state argument so you can
avoid the cast to AsyncResult.

You might want to encapsulate this functionality in a class. You could
create a GetLabourWIPAsync method and an event that is raised when the
asynchronous operation has completed. Or, you can create
BeginGetLabourWIP and EndGetLabourWIP methods. See the links below for
more info.

In the .NET 2.0 framework you can use a BackgroundWorker component instead
of a delegate to provide the same functionality, along with some extra
functionality such as a progress callback and optional cancellation.
BackgroundWorker can be used in the designer.

Async design pattern on MSDN:
http://msdn.microsoft.com/library/de...rnoverview.asp

Event-based async pattern on MSDN:
http://msdn2.microsoft.com/en-us/library/wewwczdw.aspx

Best practices for event-based async pattern on MSDN:
http://msdn2.microsoft.com/en-us/library/ms228974.aspx

--
Dave Sexton

"ChrisM" <ch**************@suedeyahoo.comwrote in message
news:u1**************@TK2MSFTNGP04.phx.gbl...
Hi,

I'm trying to get my head round Async. procedure calls.

I have the following code:

delegate double GetLabourWIPDelegate(DateTime reqDate);
...
GetLabourWIPDelegate getLabourWIPDelegate = new
GetLabourWIPDelegate(GetLabourWIPOnDate);
AsyncCallback ac = new AsyncCallback(DoResult);
IAsyncResult ar =
getLabourWIPDelegate.BeginInvoke(dteToDate.Value,a c,null);
...
private void DoResult(IAsyncResult ar)
{
GetLabourWIPDelegate getLabourWIPDelegate =
(GetLabourWIPDelegate)((AsyncResult)ar).AsyncDeleg ate;
double result = getLabourWIPDelegate.EndInvoke(ar);
lblWIPLabourTo.Text = result.ToString("###,###,###,##0.00");
}

This seems to work, it starts a new thread that async. does the
calculation on the date in dteToDate ( calls GetLabourWIPOnDate), then
calls DoResult on completion which sets the label on the form to the
result of the calculation. Is is correct though?

My other question is, what happens if I want to do another calculation at
the same time. I will be calling the same calculation method, but using a
different date value, and putting the result into a different label. How
would I alter my code to do this?

Hope this makes sense, if not, please ask me to clarify anything.

Thanks,

Chris.


Sep 22 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.