Waiting for async webservices to finish.

G

Guest

when u got the IAsyncResult
call this :

ar.AsyncWaitHandle.WaitOne();
(assume u IAsncResult instance is ar)

it will wait the asnyc call to complete

optioanly , u can call
ar.IsCompleted() to decide
 
J

jabailo

Ok, I'm going to try it this way.

I wonder if there's a more efficient way to convert all those array
types into one another (!?)

ArrayList results = new ArrayList();

while((s=sr.ReadLine())!=null)
{
results.Add(as400.BegininsertPolarData(s, tableString, null, null));
}

sr.Close();

IAsyncResult[] ar
= (IAsyncResult[]) results.ToArray(typeof(IAsyncResult));

WaitHandle[] wh = new WaitHandle[ar.Length];

for(int i=0; i<ar.Length; i++)wh=ar.AsyncWaitHandle;

WaitHandle.WaitAll(wh);





Jay said:
Jabailo,
| How about the way I implemented it.
|
| Will each webservice pause the main path of execution long enough to
| complete?

No. When you use a callback as you did, the main thread will
immediately continue with what it was doing.

My understanding is the callback is executed on the same thread as the
asynchronous method was executed on.


I could probably put the callback responses into a global static
ArrayList then and use your foreach method there.

I wonder if the WaitAll can take an ArrayList as well as an array of
AsyncCallback...

Hope this helps
Jay


| Jay B. Harlow [MVP - Outlook] wrote:
|
| > Doh!
| > || Say call 66, 72 and 98 run /extremely/ slow.
| > | The ws.EndSomeMethod will wait for 66 to finish. Seeing as 67 to 71
| > finished
| > | "a long time" before 66 they return "immediately" from the
| > ws.EndSomeMethod.
| > That should read: The ws.EndSomeMethod will wait for 1 to 65 to
finish,
| > then wait as long as it takes for 66 to finish. Seeing as 67 to 71...
|
| How about the way I implemented it.
|
| Will each webservice pause the main path of execution long enough to
| complete?
|
|
| >
| > Hope this helps
| > Jay
| >
message
| > | > | jabailo,
| > || Then I run the foreach loop...what does ws.EndSomeMethod do?
Does it
| > || wait, sequentially, for each method call to finish and then
check the
| > || next method call?
| > | It waits sequentially for each method to finish, the foreach itself
| > | checks for the next method.
| > |
| > || Say call 66, 72 and 98 run /extremely/ slow.
| > | The ws.EndSomeMethod will wait for 66 to finish. Seeing as 67 to 71
| > finished
| > | "a long time" before 66 they return "immediately" from the
| > ws.EndSomeMethod.
| > | If 72 takes longer then 66, then ws.EndSomeMethod will wait for it,
| > | otherwise it returns "immediately" also, same with 98... The net
effect
| > | is the for each only really waits as long the longest running
method,
| > | plus
| > some
| > | very minor overhead...
| > |
| > |
| > || What if I do it this way (the way I'm doing it in my code now).
Will
| > || the code "wait" until all those threads have finished before
moving on?
| > || Or is that why I need a .WaitForAll()?:
| > |
| > | The for each I showed is effectively a .WaitForAll. I understand
that
| > | WaitHandle.WaitAll has an implicit limitation of 64, which is an OS
| > | limitation.
| > |
| > | The "problem" with the call back, as you are finding, is that
there is
| > | no "obvious" way to indicate to the main thread that all the
workers are
| > | finished, where as with the for each the main thread waits for each
| > | worker individually...
| > |
| > | In a project where I am using ThreadPool.QueueUserWorkItem I
increment a
| > | count when I queue an item, then decrement the count when the item
| > finishes.
| > | You may be able to use a similar technique with the callbacks,
where you
| > | release an Manual or Auto Reset Event, to release the main
thread when
| > | the count reaches zero... However I would go with the for each over
| > |
| > | Hope this helps
| > | Jay
| > |
| > | | > ||
| > || I'm a little confused about what the ws.EndSomeMethod
accomplishes.
| > ||
| > || For example, say I make 100 calls to a webservice asynchronously.
| > ||
| > || Say call 66, 72 and 98 run /extremely/ slow.
| > ||
| > || Ok, so after the while() loop, I have 100 threads, 97 have made a
| > || successful call, 3 have not finished.
| > ||
| > || Then I run the foreach loop...what does ws.EndSomeMethod do?
Does it
| > || wait, sequentially, for each method call to finish and then
check the
| > || next method call?
| > ||
| > || What if I do it this way (the way I'm doing it in my code now).
Will
| > || the code "wait" until all those threads have finished before
moving on?
| > || Or is that why I need a .WaitForAll()?:
| > ||
| > ||
| > || while((s=sr.ReadLine())!=null)
| > || {
| > || this.as400maketable(s,tableString);
| > || }
| > ||
| > || private void as400maketable(string line, string tablename)
| > || {
| > || AsyncCallback delCB = new AsyncCallback(this.AsyncCB);
| > || as400.BegininsertPolarData(line, tablename, delCB, null);
| > || }
| > ||
| > || void AsyncCB(IAsyncResult ar)
| > || {
| > || as400.EndinsertPolarData(ar);
| > || }
| > ||
| > ||
| > || Jay B. Harlow [MVP - Outlook] wrote:
| > || > jabailo,
| > || > The "easiest" way is to put the IAsyncResult that each of the
web
| > | service
| > || > Begin* calls returns into a collection (ArrayList for
example) then
| > call
| > | the
| > || > web service End* calls for each entry in the collection.
| > || >
| > || > Something like:
| > || >
| > || > YourWebService ws = new YourWebService();
| > || >
| > || > ArrayList results = new ArrayList();
| > || >
| > || > String line = null;
| > || > while (line != null)
| > || > {
| > || > results.Add(ws.BeginSomeMethod(line, null, null));
| > || > line = reader.ReadLine();
| > || > }
| > || >
| > || > foreach(IAsyncResult result in results)
| > || > {
| > || > ws.EndSomeMethod(result);
| > || > }
| > || >
| > || > You may want to wrap the EndSomeMethod in a try/catch within
the loop
| > as
| > | it
| > || > may throw an exception...
| > || >
| > || > Hope this helps
| > || > Jay
| > || >
| > || >
| > || > | > || > |
| > || > |
| > || > | I am looping through a text file, and with each row, I
launch a web
| > || > service,
| > || > | asynchronously.
| > || > |
| > || > | Before I move on to the next step in the process, I want to
make
| > || > | sure
| > | that
| > || > | all the web services have completed.
| > || > |
| > || > | How can I do this?
| > || > |
| > || > | If I were to just put a Thread.Sleep with some arbitrary
number (
| > || > | say
| > | 5
| > || > | minutes ) would the asynch web services continue to
process? Or
| > would
| > || > they
| > || > | be frozen while the main thread sleeps?
| > || > |
| > || > |
| > || > |
| > || > |
| > || > | --
| > || > | Texeme Textcasting Technology
| > || > | http://www.texeme.com
| > || >
| > || >
| > |
| > |
|
| -- | Texeme Textcasting Technology
| http://www.texeme.com
 
J

jabailo

Scratch that -- guess I'm doing it your way :D


6/22/2005 3:34:23 PM:System.NotSupportedException: The number of
WaitHandles must be less than or equal to 64.
at System.Threading.WaitHandle.WaitAll(WaitHandle[] waitHandles,
Int32 millisecondsTimeout, Boolean exitContext)
at System.Threading.WaitHandle.WaitAll(WaitHandle[] waitHandles)
at PolarFW.PolarFW.as400insert(String FileName) in c:\documents and
settings\jbailo\my documents\visual studio
projects\cryptserv\psebank\polarfw.cs:line 480




Ok, I'm going to try it this way.

I wonder if there's a more efficient way to convert all those array
types into one another (!?)

ArrayList results = new ArrayList();

while((s=sr.ReadLine())!=null)
{
results.Add(as400.BegininsertPolarData(s, tableString, null, null));
}

sr.Close();

IAsyncResult[] ar
= (IAsyncResult[]) results.ToArray(typeof(IAsyncResult));

WaitHandle[] wh = new WaitHandle[ar.Length];

for(int i=0; i<ar.Length; i++)wh=ar.AsyncWaitHandle;

WaitHandle.WaitAll(wh);





Jay said:
Jabailo,
| How about the way I implemented it.
|
| Will each webservice pause the main path of execution long enough to
| complete?

No. When you use a callback as you did, the main thread will
immediately continue with what it was doing.

My understanding is the callback is executed on the same thread as
the asynchronous method was executed on.



I could probably put the callback responses into a global static
ArrayList then and use your foreach method there.

I wonder if the WaitAll can take an ArrayList as well as an array of
AsyncCallback...

Hope this helps
Jay


| Jay B. Harlow [MVP - Outlook] wrote:
|
| > Doh!
| > || Say call 66, 72 and 98 run /extremely/ slow.
| > | The ws.EndSomeMethod will wait for 66 to finish. Seeing as 67
to 71
| > finished
| > | "a long time" before 66 they return "immediately" from the
| > ws.EndSomeMethod.
| > That should read: The ws.EndSomeMethod will wait for 1 to 65 to
finish,
| > then wait as long as it takes for 66 to finish. Seeing as 67 to
71...
|
| How about the way I implemented it.
|
| Will each webservice pause the main path of execution long enough to
| complete?
|
|
| >
| > Hope this helps
| > Jay
| >
message
| > | > | jabailo,
| > || Then I run the foreach loop...what does ws.EndSomeMethod do?
Does it
| > || wait, sequentially, for each method call to finish and then
check the
| > || next method call?
| > | It waits sequentially for each method to finish, the foreach
itself
| > | checks for the next method.
| > |
| > || Say call 66, 72 and 98 run /extremely/ slow.
| > | The ws.EndSomeMethod will wait for 66 to finish. Seeing as 67
to 71
| > finished
| > | "a long time" before 66 they return "immediately" from the
| > ws.EndSomeMethod.
| > | If 72 takes longer then 66, then ws.EndSomeMethod will wait for
it,
| > | otherwise it returns "immediately" also, same with 98... The
net effect
| > | is the for each only really waits as long the longest running
method,
| > | plus
| > some
| > | very minor overhead...
| > |
| > |
| > || What if I do it this way (the way I'm doing it in my code
now). Will
| > || the code "wait" until all those threads have finished before
moving on?
| > || Or is that why I need a .WaitForAll()?:
| > |
| > | The for each I showed is effectively a .WaitForAll. I
understand that
| > | WaitHandle.WaitAll has an implicit limitation of 64, which is
an OS
| > | limitation.
| > |
| > | The "problem" with the call back, as you are finding, is that
there is
| > | no "obvious" way to indicate to the main thread that all the
workers are
| > | finished, where as with the for each the main thread waits for
each
| > | worker individually...
| > |
| > | In a project where I am using ThreadPool.QueueUserWorkItem I
increment a
| > | count when I queue an item, then decrement the count when the item
| > finishes.
| > | You may be able to use a similar technique with the callbacks,
where you
| > | release an Manual or Auto Reset Event, to release the main
thread when
| > | the count reaches zero... However I would go with the for each
over
| > |
| > | Hope this helps
| > | Jay
| > |
| > | | > ||
| > || I'm a little confused about what the ws.EndSomeMethod
accomplishes.
| > ||
| > || For example, say I make 100 calls to a webservice asynchronously.
| > ||
| > || Say call 66, 72 and 98 run /extremely/ slow.
| > ||
| > || Ok, so after the while() loop, I have 100 threads, 97 have made a
| > || successful call, 3 have not finished.
| > ||
| > || Then I run the foreach loop...what does ws.EndSomeMethod do?
Does it
| > || wait, sequentially, for each method call to finish and then
check the
| > || next method call?
| > ||
| > || What if I do it this way (the way I'm doing it in my code
now). Will
| > || the code "wait" until all those threads have finished before
moving on?
| > || Or is that why I need a .WaitForAll()?:
| > ||
| > ||
| > || while((s=sr.ReadLine())!=null)
| > || {
| > || this.as400maketable(s,tableString);
| > || }
| > ||
| > || private void as400maketable(string line, string tablename)
| > || {
| > || AsyncCallback delCB = new AsyncCallback(this.AsyncCB);
| > || as400.BegininsertPolarData(line, tablename, delCB, null);
| > || }
| > ||
| > || void AsyncCB(IAsyncResult ar)
| > || {
| > || as400.EndinsertPolarData(ar);
| > || }
| > ||
| > ||
| > || Jay B. Harlow [MVP - Outlook] wrote:
| > || > jabailo,
| > || > The "easiest" way is to put the IAsyncResult that each of
the web
| > | service
| > || > Begin* calls returns into a collection (ArrayList for
example) then
| > call
| > | the
| > || > web service End* calls for each entry in the collection.
| > || >
| > || > Something like:
| > || >
| > || > YourWebService ws = new YourWebService();
| > || >
| > || > ArrayList results = new ArrayList();
| > || >
| > || > String line = null;
| > || > while (line != null)
| > || > {
| > || > results.Add(ws.BeginSomeMethod(line, null, null));
| > || > line = reader.ReadLine();
| > || > }
| > || >
| > || > foreach(IAsyncResult result in results)
| > || > {
| > || > ws.EndSomeMethod(result);
| > || > }
| > || >
| > || > You may want to wrap the EndSomeMethod in a try/catch within
the loop
| > as
| > | it
| > || > may throw an exception...
| > || >
| > || > Hope this helps
| > || > Jay
| > || >
| > || >
| > || > | > || > |
| > || > |
| > || > | I am looping through a text file, and with each row, I
launch a web
| > || > service,
| > || > | asynchronously.
| > || > |
| > || > | Before I move on to the next step in the process, I want
to make
| > || > | sure
| > | that
| > || > | all the web services have completed.
| > || > |
| > || > | How can I do this?
| > || > |
| > || > | If I were to just put a Thread.Sleep with some arbitrary
number (
| > || > | say
| > | 5
| > || > | minutes ) would the asynch web services continue to
process? Or
| > would
| > || > they
| > || > | be frozen while the main thread sleeps?
| > || > |
| > || > |
| > || > |
| > || > |
| > || > | --
| > || > | Texeme Textcasting Technology
| > || > | http://www.texeme.com
| > || >
| > || >
| > |
| > |
|
| -- | Texeme Textcasting Technology
| http://www.texeme.com
 
J

jabailo

You method didn't quite seem to work either.

It through errors when trying to iterate through results.

I'm wondering if the completion of the BeginSomeMethod removes the
IAsyncHandle -- so no EndSomeMethod is possible on some elements of results.
 
J

jabailo

Ok, after trying a bunch of things, I found that I was being thrown off
by calling the web service locally from my XP machine via studio.

Somehow, it didn't have the power to keep up with some many asynchronous
requests. I then configured the web service to be dynamic in my
client so I could point it to a production deployment running on a w2k
server.

After that I used a mix of the methods suggested here.

I used an ArrayList ( great idea, because since I'm reading a file line
by line, I dont' know in advance how many calls I'm making ).

I can't use the WaitHandles because it's limited to 64.

So, I put the IAsyncResult into the array list and then call the
IsCompleted() method in a while loop on each element.
 
D

Dmytro Lapshyn [MVP]

Hi,

I'd keep an array of the async delegates themselves and call EndInvoke on
each of the delegates in a loop. Thus, you won't be wasting CPU cycles on
polling the array of IAsyncResult references in a loop.
 
J

Jay B. Harlow [MVP - Outlook]

jabailo,
That seems like a lot of work, when this will do the same thing:

| ArrayList results = new ArrayList();
|
| while((s=sr.ReadLine())!=null)
| {
| results.Add(as400.BegininsertPolarData(s, tableString, null, null));
| }
|
| sr.Close();

foreach(IAsyncResult result in results)
{
ws.EndSomeMethod(result);
}

As you avoid 2 temporary arrays (GC friendly), plus you avoid copying
elements between the 3 arrays (time friendly).

Also as you found the WaitHandle.WaitAll(wh) has a 64 WaitHandle limit, if
your file is more then 64 lines you will have a problem, the above foreach
will not!

In both cases the Main thread will have waited until all the asynchronous
results are finished.

Hope this helps
Jay

|
| Ok, I'm going to try it this way.
|
| I wonder if there's a more efficient way to convert all those array
| types into one another (!?)
|
| ArrayList results = new ArrayList();
|
| while((s=sr.ReadLine())!=null)
| {
| results.Add(as400.BegininsertPolarData(s, tableString, null, null));
| }
|
| sr.Close();
|
| IAsyncResult[] ar
| = (IAsyncResult[]) results.ToArray(typeof(IAsyncResult));
|
| WaitHandle[] wh = new WaitHandle[ar.Length];
|
| for(int i=0; i<ar.Length; i++)wh=ar.AsyncWaitHandle;
|
| WaitHandle.WaitAll(wh);
|
|
|
|
|
| (e-mail address removed) wrote:
| > Jay B. Harlow [MVP - Outlook] wrote:
| >
| >> Jabailo,
| >> | How about the way I implemented it.
| >> |
| >> | Will each webservice pause the main path of execution long enough to
| >> | complete?
| >>
| >> No. When you use a callback as you did, the main thread will
| >> immediately continue with what it was doing.
| >>
| >> My understanding is the callback is executed on the same thread as the
| >> asynchronous method was executed on.
| >
| >
| > I could probably put the callback responses into a global static
| > ArrayList then and use your foreach method there.
| >
| > I wonder if the WaitAll can take an ArrayList as well as an array of
| > AsyncCallback...
| >
| >
| >>
| >> Hope this helps
| >> Jay
| >>
| >>
| >> | >> | Jay B. Harlow [MVP - Outlook] wrote:
| >> |
| >> | > Doh!
| >> | > || Say call 66, 72 and 98 run /extremely/ slow.
| >> | > | The ws.EndSomeMethod will wait for 66 to finish. Seeing as 67 to
71
| >> | > finished
| >> | > | "a long time" before 66 they return "immediately" from the
| >> | > ws.EndSomeMethod.
| >> | > That should read: The ws.EndSomeMethod will wait for 1 to 65 to
| >> finish,
| >> | > then wait as long as it takes for 66 to finish. Seeing as 67 to
71...
| >> |
| >> | How about the way I implemented it.
| >> |
| >> | Will each webservice pause the main path of execution long enough to
| >> | complete?
| >> |
| >> |
| >> | >
| >> | > Hope this helps
| >> | > Jay
| >> | >
| >> message
| >> | > | >> | > | jabailo,
| >> | > || Then I run the foreach loop...what does ws.EndSomeMethod do?
| >> Does it
| >> | > || wait, sequentially, for each method call to finish and then
| >> check the
| >> | > || next method call?
| >> | > | It waits sequentially for each method to finish, the foreach
itself
| >> | > | checks for the next method.
| >> | > |
| >> | > || Say call 66, 72 and 98 run /extremely/ slow.
| >> | > | The ws.EndSomeMethod will wait for 66 to finish. Seeing as 67 to
71
| >> | > finished
| >> | > | "a long time" before 66 they return "immediately" from the
| >> | > ws.EndSomeMethod.
| >> | > | If 72 takes longer then 66, then ws.EndSomeMethod will wait for
it,
| >> | > | otherwise it returns "immediately" also, same with 98... The net
| >> effect
| >> | > | is the for each only really waits as long the longest running
| >> method,
| >> | > | plus
| >> | > some
| >> | > | very minor overhead...
| >> | > |
| >> | > |
| >> | > || What if I do it this way (the way I'm doing it in my code now).
| >> Will
| >> | > || the code "wait" until all those threads have finished before
| >> moving on?
| >> | > || Or is that why I need a .WaitForAll()?:
| >> | > |
| >> | > | The for each I showed is effectively a .WaitForAll. I understand
| >> that
| >> | > | WaitHandle.WaitAll has an implicit limitation of 64, which is an
OS
| >> | > | limitation.
| >> | > |
| >> | > | The "problem" with the call back, as you are finding, is that
| >> there is
| >> | > | no "obvious" way to indicate to the main thread that all the
| >> workers are
| >> | > | finished, where as with the for each the main thread waits for
each
| >> | > | worker individually...
| >> | > |
| >> | > | In a project where I am using ThreadPool.QueueUserWorkItem I
| >> increment a
| >> | > | count when I queue an item, then decrement the count when the
item
| >> | > finishes.
| >> | > | You may be able to use a similar technique with the callbacks,
| >> where you
| >> | > | release an Manual or Auto Reset Event, to release the main
| >> thread when
| >> | > | the count reaches zero... However I would go with the for each
over
| >> | > |
| >> | > | Hope this helps
| >> | > | Jay
| >> | > |
| >> | > | | >> | > ||
| >> | > || I'm a little confused about what the ws.EndSomeMethod
| >> accomplishes.
| >> | > ||
| >> | > || For example, say I make 100 calls to a webservice
asynchronously.
| >> | > ||
| >> | > || Say call 66, 72 and 98 run /extremely/ slow.
| >> | > ||
| >> | > || Ok, so after the while() loop, I have 100 threads, 97 have made
a
| >> | > || successful call, 3 have not finished.
| >> | > ||
| >> | > || Then I run the foreach loop...what does ws.EndSomeMethod do?
| >> Does it
| >> | > || wait, sequentially, for each method call to finish and then
| >> check the
| >> | > || next method call?
| >> | > ||
| >> | > || What if I do it this way (the way I'm doing it in my code now).
| >> Will
| >> | > || the code "wait" until all those threads have finished before
| >> moving on?
| >> | > || Or is that why I need a .WaitForAll()?:
| >> | > ||
| >> | > ||
| >> | > || while((s=sr.ReadLine())!=null)
| >> | > || {
| >> | > || this.as400maketable(s,tableString);
| >> | > || }
| >> | > ||
| >> | > || private void as400maketable(string line, string tablename)
| >> | > || {
| >> | > || AsyncCallback delCB = new AsyncCallback(this.AsyncCB);
| >> | > || as400.BegininsertPolarData(line, tablename, delCB, null);
| >> | > || }
| >> | > ||
| >> | > || void AsyncCB(IAsyncResult ar)
| >> | > || {
| >> | > || as400.EndinsertPolarData(ar);
| >> | > || }
| >> | > ||
| >> | > ||
| >> | > || Jay B. Harlow [MVP - Outlook] wrote:
| >> | > || > jabailo,
| >> | > || > The "easiest" way is to put the IAsyncResult that each of the
| >> web
| >> | > | service
| >> | > || > Begin* calls returns into a collection (ArrayList for
| >> example) then
| >> | > call
| >> | > | the
| >> | > || > web service End* calls for each entry in the collection.
| >> | > || >
| >> | > || > Something like:
| >> | > || >
| >> | > || > YourWebService ws = new YourWebService();
| >> | > || >
| >> | > || > ArrayList results = new ArrayList();
| >> | > || >
| >> | > || > String line = null;
| >> | > || > while (line != null)
| >> | > || > {
| >> | > || > results.Add(ws.BeginSomeMethod(line, null, null));
| >> | > || > line = reader.ReadLine();
| >> | > || > }
| >> | > || >
| >> | > || > foreach(IAsyncResult result in results)
| >> | > || > {
| >> | > || > ws.EndSomeMethod(result);
| >> | > || > }
| >> | > || >
| >> | > || > You may want to wrap the EndSomeMethod in a try/catch within
| >> the loop
| >> | > as
| >> | > | it
| >> | > || > may throw an exception...
| >> | > || >
| >> | > || > Hope this helps
| >> | > || > Jay
| >> | > || >
| >> | > || >
| >> | > || > | >> | > || > |
| >> | > || > |
| >> | > || > | I am looping through a text file, and with each row, I
| >> launch a web
| >> | > || > service,
| >> | > || > | asynchronously.
| >> | > || > |
| >> | > || > | Before I move on to the next step in the process, I want to
| >> make
| >> | > || > | sure
| >> | > | that
| >> | > || > | all the web services have completed.
| >> | > || > |
| >> | > || > | How can I do this?
| >> | > || > |
| >> | > || > | If I were to just put a Thread.Sleep with some arbitrary
| >> number (
| >> | > || > | say
| >> | > | 5
| >> | > || > | minutes ) would the asynch web services continue to
| >> process? Or
| >> | > would
| >> | > || > they
| >> | > || > | be frozen while the main thread sleeps?
| >> | > || > |
| >> | > || > |
| >> | > || > |
| >> | > || > |
| >> | > || > | --
| >> | > || > | Texeme Textcasting Technology
| >> | > || > | http://www.texeme.com
| >> | > || >
| >> | > || >
| >> | > |
| >> | > |
| >> |
| >> | -- | Texeme Textcasting Technology
| >> | http://www.texeme.com
| >>
 
J

Jay B. Harlow [MVP - Outlook]

jabailo,
What specifically was the exception and/or problem?

I've used similar code in VB.NET without any problems. My sample was typed
"from memory" so I could have had a minor typo in translation...

Remember that EndSomeMethod will raise an exception if the remote
asynchronous method threw an exception.

Hope this helps
Jay

|
| You method didn't quite seem to work either.
|
| It through errors when trying to iterate through results.
|
| I'm wondering if the completion of the BeginSomeMethod removes the
| IAsyncHandle -- so no EndSomeMethod is possible on some elements of
results.
|
| Jay B. Harlow [MVP - Outlook] wrote:
| > jabailo,
| > The "easiest" way is to put the IAsyncResult that each of the web
service
| > Begin* calls returns into a collection (ArrayList for example) then call
the
| > web service End* calls for each entry in the collection.
| >
| > Something like:
| >
| > YourWebService ws = new YourWebService();
| >
| > ArrayList results = new ArrayList();
| >
| > String line = null;
| > while (line != null)
| > {
| > results.Add(ws.BeginSomeMethod(line, null, null));
| > line = reader.ReadLine();
| > }
| >
| > foreach(IAsyncResult result in results)
| > {
| > ws.EndSomeMethod(result);
| > }
| >
| > You may want to wrap the EndSomeMethod in a try/catch within the loop as
it
| > may throw an exception...
| >
| > Hope this helps
| > Jay
| >
| >
| > | > |
| > |
| > | I am looping through a text file, and with each row, I launch a web
| > service,
| > | asynchronously.
| > |
| > | Before I move on to the next step in the process, I want to make sure
that
| > | all the web services have completed.
| > |
| > | How can I do this?
| > |
| > | If I were to just put a Thread.Sleep with some arbitrary number ( say
5
| > | minutes ) would the asynch web services continue to process? Or would
| > they
| > | be frozen while the main thread sleeps?
| > |
| > |
| > |
| > |
| > | --
| > | Texeme Textcasting Technology
| > | http://www.texeme.com
| >
| >
 
J

Jay B. Harlow [MVP - Outlook]

jabailo,
| So, I put the IAsyncResult into the array list and then call the
| IsCompleted() method in a while loop on each element.
As Dmytro suggests: This is a "bad" idea as you are burning CPU cycles
polling IsCompleted, calling EndSomeMethod causes your loop to wait on a
WaitHandle under the covers, which is much friendlier.

The sample I gave should work with minimal effort.

Hope this helps
Jay

|
|
| Ok, after trying a bunch of things, I found that I was being thrown off
| by calling the web service locally from my XP machine via studio.
|
| Somehow, it didn't have the power to keep up with some many asynchronous
| requests. I then configured the web service to be dynamic in my
| client so I could point it to a production deployment running on a w2k
| server.
|
| After that I used a mix of the methods suggested here.
|
| I used an ArrayList ( great idea, because since I'm reading a file line
| by line, I dont' know in advance how many calls I'm making ).
|
| I can't use the WaitHandles because it's limited to 64.
|
| So, I put the IAsyncResult into the array list and then call the
| IsCompleted() method in a while loop on each element.
|
| BillyLiu007 wrote:
| > when u got the IAsyncResult
| > call this :
| >
| > ar.AsyncWaitHandle.WaitOne();
| > (assume u IAsncResult instance is ar)
| >
| > it will wait the asnyc call to complete
| >
| > optioanly , u can call
| > ar.IsCompleted() to decide
 
J

jabailo

Ok.

I think when I implemented that method I was still using the local web
server ( which was causing grief ).

Now that I know it was the source of our problems, I will switch back to
the method you suggest!
 
J

jabailo

Oh, actually, what I do is this:

foreach(IAsyncResult ar in results)
ar.AsyncWaitHandle.WaitOne();

So presumably it doesn't entail the spining CPU - but just raises an
event and waits until complete.
 
J

Jay B. Harlow [MVP - Outlook]

jabailo,
Although its non-conventional, that should not cause any spinning...

I would still favor EndSomeMethod over ar.AsyncWaitHandle.WaitOne.

My understanding is that the EndSomeMethod call will clean up any resources
that may have been used (such as the WaitHandle itself). Plus it ensures any
return value or Exception is returned to your process. I understand that the
EndSomeMethod should be called even when using the callback as you
originally were. Unfortunately I don't have links to where I got this
impression...

Hope this helps
Jay

|
| Oh, actually, what I do is this:
|
| foreach(IAsyncResult ar in results)
| ar.AsyncWaitHandle.WaitOne();
|
| So presumably it doesn't entail the spining CPU - but just raises an
| event and waits until complete.
|
|
|
|
| Jay B. Harlow [MVP - Outlook] wrote:
| > jabailo,
| > | So, I put the IAsyncResult into the array list and then call the
| > | IsCompleted() method in a while loop on each element.
| > As Dmytro suggests: This is a "bad" idea as you are burning CPU cycles
| > polling IsCompleted, calling EndSomeMethod causes your loop to wait on a
| > WaitHandle under the covers, which is much friendlier.
| >
| > The sample I gave should work with minimal effort.
| >
| > Hope this helps
| > Jay
| >
| > |
| > |
| > | Ok, after trying a bunch of things, I found that I was being thrown
off
| > | by calling the web service locally from my XP machine via studio.
| > |
| > | Somehow, it didn't have the power to keep up with some many
asynchronous
| > | requests. I then configured the web service to be dynamic in my
| > | client so I could point it to a production deployment running on a w2k
| > | server.
| > |
| > | After that I used a mix of the methods suggested here.
| > |
| > | I used an ArrayList ( great idea, because since I'm reading a file
line
| > | by line, I dont' know in advance how many calls I'm making ).
| > |
| > | I can't use the WaitHandles because it's limited to 64.
| > |
| > | So, I put the IAsyncResult into the array list and then call the
| > | IsCompleted() method in a while loop on each element.
| > |
| > | BillyLiu007 wrote:
| > | > when u got the IAsyncResult
| > | > call this :
| > | >
| > | > ar.AsyncWaitHandle.WaitOne();
| > | > (assume u IAsncResult instance is ar)
| > | >
| > | > it will wait the asnyc call to complete
| > | >
| > | > optioanly , u can call
| > | > ar.IsCompleted() to decide
| >
| >
 
J

jabailo

Actually, I am using both.

I keep the EndInvoke that runs on each thread...so it cleans up the
thread, on the thread, when it finishes. But the WaitOne lets me use
the handles, on the System.Thread to determine when each async thread is
finished.

So my code looks like:

while((s=sr.ReadLine())!=null)
results.Add(this.as400maketable(s,tableString));

foreach(IAsyncResult ar in results)
ar.AsyncWaitHandle.WaitOne();

private IAsyncResult as400maketable(string line, string tablename)
{
AsyncCallback delCB = new AsyncCallback(this.AsyncCB);
IAsyncResult ar = as400.BegininsertPolarData(
line, tablename, delCB, null);
return ar;
}

void AsyncCB(IAsyncResult ar)
{
as400.EndinsertPolarData(ar);
}
;





jabailo,
Although its non-conventional, that should not cause any spinning...

I would still favor EndSomeMethod over ar.AsyncWaitHandle.WaitOne.

My understanding is that the EndSomeMethod call will clean up any resources
that may have been used (such as the WaitHandle itself). Plus it ensures any
return value or Exception is returned to your process. I understand that the
EndSomeMethod should be called even when using the callback as you
originally were. Unfortunately I don't have links to where I got this
impression...

Hope this helps
Jay

|
| Oh, actually, what I do is this:
|
| foreach(IAsyncResult ar in results)
| ar.AsyncWaitHandle.WaitOne();
|
| So presumably it doesn't entail the spining CPU - but just raises an
| event and waits until complete.
|
|
|
|
| Jay B. Harlow [MVP - Outlook] wrote:
| > jabailo,
| > | So, I put the IAsyncResult into the array list and then call the
| > | IsCompleted() method in a while loop on each element.
| > As Dmytro suggests: This is a "bad" idea as you are burning CPU cycles
| > polling IsCompleted, calling EndSomeMethod causes your loop to wait on a
| > WaitHandle under the covers, which is much friendlier.
| >
| > The sample I gave should work with minimal effort.
| >
| > Hope this helps
| > Jay
| >
| > |
| > |
| > | Ok, after trying a bunch of things, I found that I was being thrown
off
| > | by calling the web service locally from my XP machine via studio.
| > |
| > | Somehow, it didn't have the power to keep up with some many
asynchronous
| > | requests. I then configured the web service to be dynamic in my
| > | client so I could point it to a production deployment running on a w2k
| > | server.
| > |
| > | After that I used a mix of the methods suggested here.
| > |
| > | I used an ArrayList ( great idea, because since I'm reading a file
line
| > | by line, I dont' know in advance how many calls I'm making ).
| > |
| > | I can't use the WaitHandles because it's limited to 64.
| > |
| > | So, I put the IAsyncResult into the array list and then call the
| > | IsCompleted() method in a while loop on each element.
| > |
| > | BillyLiu007 wrote:
| > | > when u got the IAsyncResult
| > | > call this :
| > | >
| > | > ar.AsyncWaitHandle.WaitOne();
| > | > (assume u IAsncResult instance is ar)
| > | >
| > | > it will wait the asnyc call to complete
| > | >
| > | > optioanly , u can call
| > | > ar.IsCompleted() to decide
| >
| >
 
J

Jay B. Harlow [MVP - Outlook]

jabailo,
That seems like extra work to me! :-|

You have 2 extra routines, plus you're creating an extra delegate object for
each line in the file.

Calling BegininsertPolarData & EndinsertPolarData directly seems much
simplier to me:

while((s=sr.ReadLine())!=null)
results.Add(as400.BegininsertPolarData(s, tableString, null, null);

foreach(IAsyncResult ar in results)
as400.EndinsertPolarData(ar);

I don't really see what your extra code is buying you that the above code
gives you?

Hope this helps
Jay


| Actually, I am using both.
|
| I keep the EndInvoke that runs on each thread...so it cleans up the
| thread, on the thread, when it finishes. But the WaitOne lets me use
| the handles, on the System.Thread to determine when each async thread is
| finished.
|
| So my code looks like:
|
| while((s=sr.ReadLine())!=null)
| results.Add(this.as400maketable(s,tableString));
|
| foreach(IAsyncResult ar in results)
| ar.AsyncWaitHandle.WaitOne();
|
| private IAsyncResult as400maketable(string line, string tablename)
| {
| AsyncCallback delCB = new AsyncCallback(this.AsyncCB);
| IAsyncResult ar = as400.BegininsertPolarData(
| line, tablename, delCB, null);
| return ar;
| }
|
| void AsyncCB(IAsyncResult ar)
| {
| as400.EndinsertPolarData(ar);
| }
| ;
|
<<snip>>
 
J

jabailo

Well, by doing it my way, I can allow any thread to run to completion
and clean up asynchronously before polling it to determine if its finished.

So I use my parallel time more efficiently, and minimize my serial time.
 
J

Jay B. Harlow [MVP - Outlook]

Jabailo,
Both methods allow any thread to run to completion. Neither method polls to
determine if its finished per se.

Both methods use parallel time efficiently & both minimize serial time.

The only advantage there may be is "clean up asynchronously", however that
feels like a perceived advantage. I would not use a perceived advantage,
especially when it complicates the code.

Remember the 80/20 rule. That is 80% of the execution time of your program
is spent in 20% of your code. I will optimize (worry about performance,
memory consumption) the 20% once that 20% has been identified & proven to be
a performance problem via profiling (CLR Profiler is one profiling tool).

For info on the 80/20 rule & optimizing only the 20% see Martin Fowler's
article "Yet Another Optimization Article" at
http://martinfowler.com/ieeeSoftware/yetOptimization.pdf

Obviously we are going to have to agree to disagree here. As long as you got
what works & you understand it.

Hope this helps
Jay

|
| Well, by doing it my way, I can allow any thread to run to completion
| and clean up asynchronously before polling it to determine if its
finished.
|
| So I use my parallel time more efficiently, and minimize my serial time.
|
|
| Jay B. Harlow [MVP - Outlook] wrote:
| > jabailo,
| > That seems like extra work to me! :-|
| >
| > You have 2 extra routines, plus you're creating an extra delegate object
for
| > each line in the file.
| >
| > Calling BegininsertPolarData & EndinsertPolarData directly seems much
| > simplier to me:
| >
| > while((s=sr.ReadLine())!=null)
| > results.Add(as400.BegininsertPolarData(s, tableString, null,
null);
| >
| > foreach(IAsyncResult ar in results)
| > as400.EndinsertPolarData(ar);
| >
| > I don't really see what your extra code is buying you that the above
code
| > gives you?
| >
| > Hope this helps
| > Jay
| >
| >
| > | Actually, I am using both.
| > |
| > | I keep the EndInvoke that runs on each thread...so it cleans up the
| > | thread, on the thread, when it finishes. But the WaitOne lets me use
| > | the handles, on the System.Thread to determine when each async thread
is
| > | finished.
| > |
| > | So my code looks like:
| > |
| > | while((s=sr.ReadLine())!=null)
| > | results.Add(this.as400maketable(s,tableString));
| > |
| > | foreach(IAsyncResult ar in results)
| > | ar.AsyncWaitHandle.WaitOne();
| > |
| > | private IAsyncResult as400maketable(string line, string tablename)
| > | {
| > | AsyncCallback delCB = new AsyncCallback(this.AsyncCB);
| > | IAsyncResult ar = as400.BegininsertPolarData(
| > | line, tablename, delCB, null);
| > | return ar;
| > | }
| > |
| > | void AsyncCB(IAsyncResult ar)
| > | {
| > | as400.EndinsertPolarData(ar);
| > | }
| > | ;
| > |
| > <<snip>>
| >
| >
 
J

jabailo

Dmytro said:
Hi,

I'd keep an array of the async delegates themselves and call EndInvoke
on each of the delegates in a loop. Thus, you won't be wasting CPU
cycles on polling the array of IAsyncResult references in a loop.

The limit on that is 64.
 
D

Dmytro Lapshyn [MVP]

At a time (because it's the WaitForMultipleObjects API limitation), but not
for a sequential poll, I guess.
 
J

John Bailo

Dmytro said:
At a time (because it's the WaitForMultipleObjects API limitation), but
not for a sequential poll, I guess.

Someone suggested launching them in blocks.

So you could launch 64, wait for the callback, and so on.

Still -- to me -- with a powerful dual proc web server, I would expect that
it would be able to handle hundreds of thousands of calls to a web service
simultaneously ( just like serving hundreds of thousands of web pages ).
 
M

m.posseth

i follow this verry interesting thread but one thing keeps spinning in my
mind

my question to you would be

why do you call it asynchronous ?????

i do not see anny advantage for you to do so

make it a synchronous call ,, and it is probably much faster in this
situation ( ofcourse depending on your design :)

Michel Posseth [MCP]
 

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