473,394 Members | 1,878 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

best way to wait for async delegate calls to complete

Hi,
I've omitted a large chunk of the code for clarity but the loop below is how
I'm calling a delegate function asynchronously. After I start the each call
I'm incrementing a counter and then making the main thread sleep until the
counter gets back to zero. The call back function for each call decrements
the counter. Is there a better way to make the thread wait until all calls
are complete besides using the counter? I've seen some things with using an
IAsyncResult but I'm not sure how to do that in my case since I'm making 1
to n calls.
Thanks,
Ryan

For iProviderIndex As Int32 = 0 To oProviders.Length - 1
oLookupReq = New Schema.LookupRequest
oLookup =
CType(Activator.CreateInstance(Type.GetType(oLooku pType.class_id)),
Schema.IPrequalLookup)
Del = New LookupAsyncDelegate(AddressOf oLookup.GetPrequalResponse)
Del.BeginInvoke(oLookupReq, AddressOf LookupCallback, Del)
IncrementAsyncOps()
Next iProviderIndex

While m_async_ops > 0
Thread.Sleep(200)
End While
Nov 21 '05 #1
11 6901
well there are always other aproaches , your solution has the big advantage
of simplicity
another aproach could be to write your todo code in a class , start these on
another thread and keep track of them with a queue class

if i think a litle more i know for sure that i can find other constructions
to get the job done , however your aproach isn`t so bad at all
and has the big advantage in my opinion that it is clear in what it does

IAsyncResult will give you a value back from the method , i do not see how
this could help in this situation

regards

Michel Posseth [MCP]


"ryan" <ro*************@inval.hotmail.com> schreef in bericht
news:eI**************@TK2MSFTNGP09.phx.gbl...
Hi,
I've omitted a large chunk of the code for clarity but the loop below is
how I'm calling a delegate function asynchronously. After I start the each
call I'm incrementing a counter and then making the main thread sleep
until the counter gets back to zero. The call back function for each call
decrements the counter. Is there a better way to make the thread wait
until all calls are complete besides using the counter? I've seen some
things with using an IAsyncResult but I'm not sure how to do that in my
case since I'm making 1 to n calls.
Thanks,
Ryan

For iProviderIndex As Int32 = 0 To oProviders.Length - 1
oLookupReq = New Schema.LookupRequest
oLookup =
CType(Activator.CreateInstance(Type.GetType(oLooku pType.class_id)),
Schema.IPrequalLookup)
Del = New LookupAsyncDelegate(AddressOf oLookup.GetPrequalResponse)
Del.BeginInvoke(oLookupReq, AddressOf LookupCallback, Del)
IncrementAsyncOps()
Next iProviderIndex

While m_async_ops > 0
Thread.Sleep(200)
End While

Nov 21 '05 #2
Ryan,

You could use the ManualResetEvent class. Create a ManualResetEvent
before the loop. Have the LookupCallback method signal the event by
calling the Set method when the m_async_ops counter gets down to 0.
After the loop wait for the event by calling the WaitOne method. I
recommend setting the m_async_ops counter's initial value to the number
of delegates your are going to invoke before the loop though.
Otherwise, you may get strange results if you're not careful.

Also, the code you've posted is not thread-safe. The while loop
checking to see if m_async_ops is > 0 may never end. The reason is
because that thread may not be seeing the changes other threads are
making. You need to have some synchronization mechanism in place to at
least do a volatile read of m_async_ops.

Brian

ryan wrote:
Hi,
I've omitted a large chunk of the code for clarity but the loop below is how
I'm calling a delegate function asynchronously. After I start the each call
I'm incrementing a counter and then making the main thread sleep until the
counter gets back to zero. The call back function for each call decrements
the counter. Is there a better way to make the thread wait until all calls
are complete besides using the counter? I've seen some things with using an
IAsyncResult but I'm not sure how to do that in my case since I'm making 1
to n calls.
Thanks,
Ryan

For iProviderIndex As Int32 = 0 To oProviders.Length - 1
oLookupReq = New Schema.LookupRequest
oLookup =
CType(Activator.CreateInstance(Type.GetType(oLooku pType.class_id)),
Schema.IPrequalLookup)
Del = New LookupAsyncDelegate(AddressOf oLookup.GetPrequalResponse)
Del.BeginInvoke(oLookupReq, AddressOf LookupCallback, Del)
IncrementAsyncOps()
Next iProviderIndex

While m_async_ops > 0
Thread.Sleep(200)
End While


Nov 21 '05 #3
Ryan,
In addition to the other comments:

I would store the IAsyncResult values returned from BeginInvoke in a list,
that I then did a For Each over doing an EndInvoke on each one in turn.

Something like:

Public Delegate Sub DoSomething()

Public Shared Sub Something()
System.Threading.Thread.Sleep(TimeSpan.FromSeconds (0.5))
End Sub

Public Shared Sub Main()
Dim method As DoSomething = AddressOf Something
Dim results As New ArrayList

For index As Integer = 1 To 100
Dim result As IAsyncResult = method.BeginInvoke(Nothing,
Nothing)
results.Add(result)
Next

For Each result As IAsyncResult In results
Try
method.EndInvoke(result)
Catch ex As Exception
' report the error but keep going...
Debug.WriteLine(ex, "End Invoke")
End Try
Next

End Sub

This allows the main thread to quietly wait until all the workers are
finished. Because the workers are finishing asynchronously the EndInvoke
will either return really quickly for completed workers or wait for busy
workers...

Note depending on the method called, you may want to store the Delegate
itself (the method variable) in the list also or as the AsyncState on the
BeginInvoke call...

--
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net
"ryan" <ro*************@inval.hotmail.com> wrote in message
news:eI**************@TK2MSFTNGP09.phx.gbl...
| Hi,
| I've omitted a large chunk of the code for clarity but the loop below is
how
| I'm calling a delegate function asynchronously. After I start the each
call
| I'm incrementing a counter and then making the main thread sleep until the
| counter gets back to zero. The call back function for each call decrements
| the counter. Is there a better way to make the thread wait until all calls
| are complete besides using the counter? I've seen some things with using
an
| IAsyncResult but I'm not sure how to do that in my case since I'm making 1
| to n calls.
| Thanks,
| Ryan
|
| For iProviderIndex As Int32 = 0 To oProviders.Length - 1
| oLookupReq = New Schema.LookupRequest
| oLookup =
| CType(Activator.CreateInstance(Type.GetType(oLooku pType.class_id)),
| Schema.IPrequalLookup)
| Del = New LookupAsyncDelegate(AddressOf oLookup.GetPrequalResponse)
| Del.BeginInvoke(oLookupReq, AddressOf LookupCallback, Del)
| IncrementAsyncOps()
| Next iProviderIndex
|
| While m_async_ops > 0
| Thread.Sleep(200)
| End While
|
|
Nov 21 '05 #4
Thanks for all of the quick responses. I'll try out these different methods
over the weekend.

Brian, as far as the m_async_ops variable goes, I am using
Interlocked.Increment and Interlocked.Decrement to change the value
m_async_ops. Won't those block another thread from reading the value or do I
need to also use some sort of synchronization while I read?

Jay, right now I'm calling the EndInvoke in the LookupCallback routine which
happens immediately when each call is finished. Is there any problems with
not calling the EndInvoke immediately? For instance, if the loop makes 5
calls and the first one happens to take 30 seconds and the other 4 take on 1
second. The first EndInvoke call will be blocking for 30 seconds even though
the other calls are finished. That reminds me of another question I have.
With the way I currently have it, does my callback function run under the
main thread or the thread that the acync call runs under?

thanks again,
Ryan

"ryan" <ro*************@inval.hotmail.com> wrote in message
news:eI**************@TK2MSFTNGP09.phx.gbl...
Hi,
I've omitted a large chunk of the code for clarity but the loop below is
how I'm calling a delegate function asynchronously. After I start the each
call I'm incrementing a counter and then making the main thread sleep
until the counter gets back to zero. The call back function for each call
decrements the counter. Is there a better way to make the thread wait
until all calls are complete besides using the counter? I've seen some
things with using an IAsyncResult but I'm not sure how to do that in my
case since I'm making 1 to n calls.
Thanks,
Ryan

For iProviderIndex As Int32 = 0 To oProviders.Length - 1
oLookupReq = New Schema.LookupRequest
oLookup =
CType(Activator.CreateInstance(Type.GetType(oLooku pType.class_id)),
Schema.IPrequalLookup)
Del = New LookupAsyncDelegate(AddressOf oLookup.GetPrequalResponse)
Del.BeginInvoke(oLookupReq, AddressOf LookupCallback, Del)
IncrementAsyncOps()
Next iProviderIndex

While m_async_ops > 0
Thread.Sleep(200)
End While

Nov 21 '05 #5
Ryan,

Go with Jay's idea. It's much better. In fact, that's the way I did a
similar chore in the past so I'm not really sure what I was thinking
when I suggested the alternative. My other comments are inline.

ryan wrote:
Thanks for all of the quick responses. I'll try out these different methods
over the weekend.

Brian, as far as the m_async_ops variable goes, I am using
Interlocked.Increment and Interlocked.Decrement to change the value
m_async_ops. Won't those block another thread from reading the value or do I
need to also use some sort of synchronization while I read?

Yes, you need to use some sort of synchronization during reads as well.
No, technically the Interlocked methods don't block other threads from
reading the value, but that's not the issue anyway. The issue is with
memory barriers, or more specifically, the lack thereof in this case.
A memory barrier basically tells the hardware to fetch the value from
main memory instead of using a register or on-chip cache. Likewise,
during writes it tells the hardware to go ahead and write to main
memory. The Interlocked class, like all of the synchronization
primitives, creates the memory barrier so the writes you make on other
threads will be flushed to main memory, but other threads that are
reading the counter are not guarenteed to see those changes. There are
several options:

1) Use SyncLock for both reading and writing to m_async_ops.

2) Use the Interlocked.CompareExchange method to read the value. It's
a little odd how this works so I have provided an example.

While Interlocked.CompareExchange(m_async_ops, m_async_ops,
m_async_ops) > 0
Thread.Sleep(200)
End While

3) Use Thread.VolatileRead.

4) In C# you could mark m_async_ops with the volatile keyword.

Personally, I would use #1, but the others are acceptable as well.

Read this article for more information.

<http://www.yoda.arachsys.com/csharp/threads/volatility.shtml>
Jay, right now I'm calling the EndInvoke in the LookupCallback routine which
happens immediately when each call is finished. Is there any problems with
not calling the EndInvoke immediately? For instance, if the loop makes 5
calls and the first one happens to take 30 seconds and the other 4 take on 1
second. The first EndInvoke call will be blocking for 30 seconds even though
the other calls are finished.
Yes, that's perfectly acceptable.
That reminds me of another question I have.
With the way I currently have it, does my callback function run under the
main thread or the thread that the acync call runs under?
It runs on the thread that the async call to your delegate runs on. It
isn't the thread that called Delegate.BeginInvoke.
thanks again,
Ryan


Nov 21 '05 #6
Michael,

Is it not possible that the queue can lockup the process because of the
limit of the amount of parallel processed threads?

Another disadvantage can be that by the queue in fact the processes are
accessed sequential at the moment the start to become ready.

(Just a thought reading your message, not really deeply investigated).

:-)

Cor
Nov 21 '05 #7
Thanks for the enlightenment. I always though it was safe to read a value
without synchronization. I'll change it to use SyncLock.
"Brian Gideon" <br*********@yahoo.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
Ryan,

Go with Jay's idea. It's much better. In fact, that's the way I did a
similar chore in the past so I'm not really sure what I was thinking
when I suggested the alternative. My other comments are inline.

ryan wrote:
Thanks for all of the quick responses. I'll try out these different
methods
over the weekend.

Brian, as far as the m_async_ops variable goes, I am using
Interlocked.Increment and Interlocked.Decrement to change the value
m_async_ops. Won't those block another thread from reading the value or
do I
need to also use some sort of synchronization while I read?


Yes, you need to use some sort of synchronization during reads as well.
No, technically the Interlocked methods don't block other threads from
reading the value, but that's not the issue anyway. The issue is with
memory barriers, or more specifically, the lack thereof in this case.
A memory barrier basically tells the hardware to fetch the value from
main memory instead of using a register or on-chip cache. Likewise,
during writes it tells the hardware to go ahead and write to main
memory. The Interlocked class, like all of the synchronization
primitives, creates the memory barrier so the writes you make on other
threads will be flushed to main memory, but other threads that are
reading the counter are not guarenteed to see those changes. There are
several options:

1) Use SyncLock for both reading and writing to m_async_ops.

2) Use the Interlocked.CompareExchange method to read the value. It's
a little odd how this works so I have provided an example.

While Interlocked.CompareExchange(m_async_ops, m_async_ops,
m_async_ops) > 0
Thread.Sleep(200)
End While

3) Use Thread.VolatileRead.

4) In C# you could mark m_async_ops with the volatile keyword.

Personally, I would use #1, but the others are acceptable as well.

Read this article for more information.

<http://www.yoda.arachsys.com/csharp/threads/volatility.shtml>
Jay, right now I'm calling the EndInvoke in the LookupCallback routine
which
happens immediately when each call is finished. Is there any problems
with
not calling the EndInvoke immediately? For instance, if the loop makes 5
calls and the first one happens to take 30 seconds and the other 4 take
on 1
second. The first EndInvoke call will be blocking for 30 seconds even
though
the other calls are finished.


Yes, that's perfectly acceptable.
That reminds me of another question I have.
With the way I currently have it, does my callback function run under the
main thread or the thread that the acync call runs under?


It runs on the thread that the async call to your delegate runs on. It
isn't the thread that called Delegate.BeginInvoke.
thanks again,
Ryan

Nov 21 '05 #8
Ryan,
| Brian, as far as the m_async_ops variable goes, I am using
| Interlocked.Increment and Interlocked.Decrement to change the value
In addition to Brian's comments: Interlocked.Decrement returns the new
decremented value, I would either use the Decrement's return value or a
SyncLock to check the variable itself.
| Jay, right now I'm calling the EndInvoke in the LookupCallback routine
which
| happens immediately when each call is finished.
I only call EndInvoke in the CallBack when no body else (such as the main
thread) cares that the async method finished or not.
| Is there any problems with
| not calling the EndInvoke immediately?
It doesn't matter when you call EndInvoke, it only matters that you call it.
If you don't call it I understand that you can leak resources.
| For instance, if the loop makes 5
| calls and the first one happens to take 30 seconds and the other 4 take on
1
| second. The first EndInvoke call will be blocking for 30 seconds even
though
| the other calls are finished.
That is the beauty of using the For Each (thinking about it, one could use a
System.Collections.Queue also). Your main process will only block for the
longest running async method, quick running async methods will return from
EndInvoke "right away".
| With the way I currently have it, does my callback function run under the
| main thread or the thread that the acync call runs under?
As Brian states the callback function runs on the thread that the ascync
call runs under.

--
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net
"ryan" <ro*************@inval.hotmail.com> wrote in message
news:OA**************@TK2MSFTNGP15.phx.gbl...
| Thanks for all of the quick responses. I'll try out these different
methods
| over the weekend.
|
| Brian, as far as the m_async_ops variable goes, I am using
| Interlocked.Increment and Interlocked.Decrement to change the value
| m_async_ops. Won't those block another thread from reading the value or do
I
| need to also use some sort of synchronization while I read?
|
| Jay, right now I'm calling the EndInvoke in the LookupCallback routine
which
| happens immediately when each call is finished. Is there any problems with
| not calling the EndInvoke immediately? For instance, if the loop makes 5
| calls and the first one happens to take 30 seconds and the other 4 take on
1
| second. The first EndInvoke call will be blocking for 30 seconds even
though
| the other calls are finished. That reminds me of another question I have.
| With the way I currently have it, does my callback function run under the
| main thread or the thread that the acync call runs under?
|
| thanks again,
| Ryan
|
|
|
| "ryan" <ro*************@inval.hotmail.com> wrote in message
| news:eI**************@TK2MSFTNGP09.phx.gbl...
| > Hi,
| > I've omitted a large chunk of the code for clarity but the loop below is
| > how I'm calling a delegate function asynchronously. After I start the
each
| > call I'm incrementing a counter and then making the main thread sleep
| > until the counter gets back to zero. The call back function for each
call
| > decrements the counter. Is there a better way to make the thread wait
| > until all calls are complete besides using the counter? I've seen some
| > things with using an IAsyncResult but I'm not sure how to do that in my
| > case since I'm making 1 to n calls.
| > Thanks,
| > Ryan
| >
| > For iProviderIndex As Int32 = 0 To oProviders.Length - 1
| > oLookupReq = New Schema.LookupRequest
| > oLookup =
| > CType(Activator.CreateInstance(Type.GetType(oLooku pType.class_id)),
| > Schema.IPrequalLookup)
| > Del = New LookupAsyncDelegate(AddressOf oLookup.GetPrequalResponse)
| > Del.BeginInvoke(oLookupReq, AddressOf LookupCallback, Del)
| > IncrementAsyncOps()
| > Next iProviderIndex
| >
| > While m_async_ops > 0
| > Thread.Sleep(200)
| > End While
| >
|
|
Nov 21 '05 #9
Well i believe it is just the other way around i.o.w. with threading and a
queue you have some control over the execution ( you could even create a
construction with prio`s etc etc ) with executing asynchronous delegates
you do not have anny control at all

if it is really about speed threading and asynchronous methods are only
interesting if your proggy runs on a multi processor system , otherwise the
overhead is to costly and it would decrease performance of your project .

in the Balena book \ and VB.net remoting ( distributed programming ) book
are some nice examples that show that threading most of the times isn`t
interesting at all because of the overhead it costs .

however in the near duall processor future it is great tech.

;-)

Michel Posseth


"Cor Ligthert [MVP]" <no************@planet.nl> schreef in bericht
news:es**************@tk2msftngp13.phx.gbl...
Michael,

Is it not possible that the queue can lockup the process because of the
limit of the amount of parallel processed threads?

Another disadvantage can be that by the queue in fact the processes are
accessed sequential at the moment the start to become ready.

(Just a thought reading your message, not really deeply investigated).

:-)

Cor

Nov 21 '05 #10
Michel,

As in your sentence about Mandarine and Spanish

We completely agree and you should see my discussions in the dotnet
newsgroup where I have stated this often. I am glad that at least I found
somebody who tells the same.

Although it can be used in a lot of situations.

Cor
Nov 21 '05 #11
Oops,

Before you understand me wrong in past I have used often queues and this
kind of programming.

However than it was with large batch programming where I was forever
paralyzing processes and for that it is great

Cor
Nov 21 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Dave | last post by:
I'm using the BeginInvoke method of a delegate to invoke a thread asynchronously and then use the EndInvoke to retrieve the value. This works wonderfully until a Serviced Component is added to...
3
by: mvdevnull | last post by:
static void Main(string args) { DoSomething(); } static void DoSomething() { for (int i=0; i<=10; i++) { CallAsyncMethod(); } } my problem is when i run the app console exists without really...
2
by: Winston Nimchan | last post by:
Hi: I am trying to develop a server application that listens for incoming network request and processes these requests. Processing request involves analyzing the packet, applying business rules,...
10
by: Shawn Meyer | last post by:
Hello - I am trying to write a class that has an async BeginX and EndX, plus the regular X syncronous method. Delegates seemed like the way to go, however, I still am having problems getting...
7
by: Shak | last post by:
Hi all, I'm trying to write a thread-safe async method to send a message of the form (type)(contents). My model is as follows: private void SendMessage(int type, string message) { //lets...
4
by: Nikolay Unguzov | last post by:
Hi, I want to know how to start two or more async methods, but wait each one to complete, before proceed to the next one. My goal is to do many time-consuming tasks one after other but not block...
3
by: Giulio Petrucci | last post by:
Hi there, I'm quite a newbie in Web Service programming/using and I'm sorry if my question could sound quite "stupid". ;-) I'm working on an application which should request a service to a...
2
by: billsahiker | last post by:
I wrote a test program to help understand asynchronous calls in c#. I have a working VB.NET app that uses a similar technique but I cannot get it to work in c#. The errors I get and the code below....
2
by: jojoba | last post by:
Hello to all! I have a fairly simple webservice running in asp.net ajax under c# (vs 2008). I built the service and it runs just dandy when i test it by itself in visual studio. However, to...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.