execute 1 method after another method has finishedhttp://forums.asp.net/t/1106663.aspx/1?execute+1+method+after+another+method+has+finishedWed, 09 May 2007 16:52:53 -040011066631694609http://forums.asp.net/p/1106663/1694609.aspx/1?execute+1+method+after+another+method+has+finishedexecute 1 method after another method has finished <p>I've got in my page load 2 methods: <font size="2"></p> <ul> <li>CallAllMethods(); </li><li>VulTabel();</li></ul> <p>Now the CallAllMethods() makes 12 calls to my webservice... And the VulTabel tries to display the results received from the webservice calls</p> <p>The problem now is that the VulTabel() is already executed before all my calls to my webservice in the CallAllMethods() is finished.</p> <p>This leads to errors in my code...</p> <p>How can i make sure that the VulTabel() method is only executed after the CallAllMethods() has finished ?</p> <pre class="prettyprint">protected void Page_Load(object sender, EventArgs e) { Master.Page.Title = &quot;Monitor - Server info&quot;; srv = new LokaleService.BMI(); CallAllMethods(); VulTabel(); if (!IsPostBack) { string serverNaam = Request.QueryString[&quot;titel&quot;]; strServerID = Request.QueryString[&quot;serverID&quot;]; serverID = System.Convert.ToInt32(serverID); lblServer.Text = serverNaam; lblServerID.Text = strServerID; ((Monitor)Master).PaginaTitel = &quot;Server info&quot;; } }</pre>&nbsp;</font> 2007-05-04T08:14:21-04:001694653http://forums.asp.net/p/1106663/1694653.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished Hi Friend,<br> <br> <br> I m not sure but it might help.<br> <font size="2"> <p></font><font color="#0000ff" size="2">try<br> </font><font size="2">{<br> CallAllMethods();<br> }<br> </font><font color="#0000ff" size="2">catch</font><font size="2"> (</font><font color="#008080" size="2">Exception</font><font size="2"> ex)<br> {}<br> </font><font color="#0000ff" size="2">finally<br> </font><font size="2">{<br> VulTabel();<br> }</p> </font> 2007-05-04T08:54:13-04:001695361http://forums.asp.net/p/1106663/1695361.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>If you are having a threading issue, then make the current thread wait (Join/Sleep) until the other thread(s) is(are) done.</p> <p>Another simple trick would automatically have your thread waiting by locking some [non-static, otherwise it will stop all page requests for one-at-a-time processing, which would be really slow] value that VulTabel will try to use.&nbsp; This will require the CallAllMethods() code to finish before VulTabel can do anything because it will be waiting for the lock to open up.</p> <p>Go with what makes sense in the implementation.&nbsp; It sounds like the Locking approach is what you want though.</p> 2007-05-04T16:30:24-04:001695404http://forums.asp.net/p/1106663/1695404.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>Please show what you're doing in 'CallAllMethods' - why does that return before all WebService calls are finished? Do you issue 12 async calls in parallell and then just return? If so, there are many ways to synchronize and wait for them to&nbsp;all finish - the most obvious&nbsp;simply waiting for all the&nbsp;WaitHandles in the IAsyncResults from the async calls.&nbsp;If they're called synchronlously something else than what you think is actually causing the error.</p> <p>By the way - if you're calling 12 web services in one request, you should really, really consider running your page in async mode.</p> 2007-05-04T17:06:55-04:001695413http://forums.asp.net/p/1106663/1695413.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>It depends on how you are calling the webservice.&nbsp; Each method in a WebService (at least those I've created with .net) has two different method calls.&nbsp; You can either call the method synchronously or asynchronously.&nbsp; For example, if you create a method called HelloWorld(), the service will give you two methods, HelloWorld() and HelloWorldAsync().&nbsp; </p> <p>If you are doing an asynchronous call to the web service, the call begins on a different thread, and your application can continue running while it is waiting for a reply.&nbsp; In this scenario you will need to wait for the HelloWorldCompleted event to fire.&nbsp; This will give you a little better performance (depending on how long each webservice call takes to complete), but it will take more time and code to get working.&nbsp; You will need to have a mechanism that waits for all the events to fire before continuing.</p> <p>Otherwise, you can call the methods synchronously, and then the method runs on the current thread, so the next line of code doesn't begin until the webcall returns.</p> <p>&nbsp;</p> 2007-05-04T17:12:35-04:001696237http://forums.asp.net/p/1106663/1696237.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <span class="kwd"><font color="#0000ff">private void</font></span> CallAllMethods()<br> &nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetServices(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackServices), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetMemory(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackMemory), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetSchijven(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackSchijven), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetMcAfee(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackMcAffee), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetLogin(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackLogins), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetApparaatbeheer(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackApparaatBeheer), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetFysiekeSchijven(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackFysSchijven), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetPrinters(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackPrinters), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetSQLStatus(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackSqlStatus), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetSymantec(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackSymantec), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetMailbox(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackMailbox), srv);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv.BeginGetSQLBackup(<span class="kwd"><font color="#0000ff">new</font></span> AsyncCallback(WsCallbackSqlBackUp), srv);<br> &nbsp;&nbsp; }<pre class="prettyprint">Each off this calls has it own CallBack method where i receive the results:</pre><pre class="prettyprint">For example:</pre><pre class="prettyprint">&nbsp;<pre class="prettyprint"> <SPAN class=kwd><FONT color=#0000ff>private void</FONT></SPAN> WsCallbackServices(IAsyncResult ar) { LokaleService.BMI srv = (LokaleService.BMI)ar.AsyncState; services = <SPAN class=kwd><FONT color=#0000ff>new</FONT></SPAN> System.Collections.ArrayList(srv.EndGetServices(ar)); } <SPAN class=kwd><FONT color=#0000ff>private void</FONT></SPAN> WsCallbackMemory(IAsyncResult ar) { LokaleService.BMI srv = (LokaleService.BMI)ar.AsyncState; memory = <SPAN class=kwd><FONT color=#0000ff>new</FONT></SPAN> System.Collections.ArrayList(srv.EndGetMemory(ar)); }</pre><pre class="prettyprint">&nbsp;</pre><pre class="prettyprint">&nbsp;</pre><pre class="prettyprint">How would i implement the wait all method?</pre></PRE> 2007-05-05T10:25:37-04:001696305http://forums.asp.net/p/1106663/1696305.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished There are several ways to do this, but the most straightforward and obvious is probably to collect the WaitHandles and the do a WaitAll. E.g.&nbsp;<pre class="prettyprint">private void CallAllMethods() { WaitHandle[] waitHandles = new WaitHandle[12]; waitHandles[0] = srv.BeginGetServices(new AsyncCallback(WsCallbackServices), srv).AsyncWaitHandle; waitHandles[1] = srv.BeginGetMemory(new AsyncCallback(WsCallbackMemory), srv).AsyncWaitHandle; // etc... WaitHandle.WaitAll(waitHandles); }</pre>&nbsp; 2007-05-05T12:16:07-04:001697772http://forums.asp.net/p/1106663/1697772.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>well, i'm not getting any null pointers now so the wait all is working but there is something strange with it...</p> <p>&nbsp;Sometimes i receive an error on the last&nbsp;call...</p> <p><font color="#008000">System.Net.WebException was unhandled by user code<br> &nbsp; Message=&quot;The request failed with HTTP status 403: Access Forbidden.&quot;<br> &nbsp; Source=&quot;System.Web.Services&quot;<br> &nbsp; StackTrace:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at System.Web.Services.Protocols.SoapHttpClientProtocol.EndInvoke(IAsyncResult asyncResult)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at LokaleService.BMI.EndGetMailbox(IAsyncResult asyncResult) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\esc\3637b088\699c85ae\App_WebReferences.vlus22rw.0.cs:line 394<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at ServerPage.WsCallbackMailbox(IAsyncResult ar) in c:\Documents and Settings\stage\Bureaublad\ESC\ServerPage.aspx.cs:line 132<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at System.Web.Services.Protocols.WebClientAsyncResult.Complete()<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at System.Web.Services.Protocols.WebClientProtocol.ProcessAsyncResponseStreamResult(WebClientAsyncResult client, IAsyncResult asyncResult)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at System.Web.Services.Protocols.WebClientProtocol.ReadAsyncResponseStream(WebClientAsyncResult client)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at System.Web.Services.Protocols.WebClientProtocol.ReadAsyncResponse(WebClientAsyncResult client)<br> </font><font color="#008000" size="2"></p> <p>waitHandles[11] = srv.BeginGetSQLBackup(new AsyncCallback(WsCallbackSqlBackUp), srv).AsyncWaitHandle;</p> <p>The error occures in the WsCallBackSqlBackUp() method:</p> <font color="#0000ff" size="2"> <p>private</font><font color="#000000" size="2"> </font><font color="#0000ff" size="2">void</font><font color="#000000" size="2"> WsCallbackMailbox(</font><font color="#008080" size="2">IAsyncResult</font><font size="2"><font color="#000000"> ar)<br> </font>{<br> &nbsp; LokaleService.</font><font color="#008080" size="2">BMI</font><font size="2"> srv = (LokaleService.</font><font color="#008080" size="2">BMI</font><font size="2">)ar.AsyncState;<br> &nbsp; mailBox = </font><font color="#0000ff" size="2">new</font><font size="2"> System.Collections.</font><font color="#008080" size="2">ArrayList</font><font size="2">(srv.EndGetMailbox(ar));<br> }</font></p> <p><font size="2">When i remove the last call, the errors occures on the new last one...</p> </font></font> 2007-05-07T07:20:28-04:001697782http://forums.asp.net/p/1106663/1697782.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>made little mistake in previous:</p> <font color="#008000" size="2"> <p>private void WsCallbackSqlBackUp(IAsyncResult ar)<br> {<br> &nbsp;&nbsp; LokaleService.BMI srv = (LokaleService.BMI)ar.AsyncState;<br> &nbsp;&nbsp; sqlBackUp = new System.Collections.ArrayList(srv.EndGetSQLBackup(ar));<br> } </p> <p>is the last method which receives the error...</p> <p>&nbsp;IF i wait for every call to return their results... isnt this the same then calling&nbsp; all the methods from the webservice synchronously ?</p> </font> 2007-05-07T07:29:39-04:001698417http://forums.asp.net/p/1106663/1698417.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p></p> <blockquote><span class="icon-blockquote"></span> <h4>tompy_nation</h4> &nbsp;<font color="#008000" size="2">&nbsp;IF i wait for every call to return their results... isnt this the same then calling&nbsp; all the methods from the webservice synchronously ?</font></blockquote> <p></p> <p>No, it's not. Using the async calls and WaitAll will launch all 12 requests &quot;simultanously&quot;, and then wait for them all to complete - which in fact will be very close to the time the longest running takes. If you run all the methods synchronously, you'll have to wait the sum of all the time each method takes.</p> 2007-05-07T15:19:34-04:001698463http://forums.asp.net/p/1106663/1698463.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p></p> <blockquote><span class="icon-blockquote"></span> <h4>tompy_nation</h4> <font color="#008000" size="2"><font size="2">When i remove the last call, the errors occures on the new last one...</font></font></blockquote> <p></p> <p>This is probably because the WaitHandle is signalled more or less at the same time as the callback is called, meaning that while you're about to execute the End... method, you're also ending the method. A variation on your original problem... So you can't do it quite that simple... You'll have to decide to either use callbacks, or the WaitHandles.</p> <p>One way to do this, is to make your own little CountedEvent class, which contains a ManualResetEvent, and a counter. Initialize an instance of this class with the counter value 12, pass the reference to the instance in the AsyncState member, and have each callback decrement the counter. When the counter reaches zero, the CountedEvent will signall it's event. The CallAllMethods will wait on that event.</p> <p>Another way is to use the WaitHandle array, but do a WaitForAny, and then process the results there until all handles are signalled. You can then use the AsyncState member to hold the callback delegate.</p> 2007-05-07T15:53:56-04:001699031http://forums.asp.net/p/1106663/1699031.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <blockquote><span class="icon-blockquote"></span> <h4>Svante</h4> <p></p> <blockquote><span class="icon-blockquote"></span> <h4>tompy_nation</h4> <font color="#008000" size="2"><font size="2">When i remove the last call, the errors occures on the new last one...</font></font></blockquote> <p></p> <p>One way to do this, is to make your own little CountedEvent class, which contains a ManualResetEvent, and a counter. Initialize an instance of this class with the counter value 12, pass the reference to the instance in the AsyncState member, and have each callback decrement the counter. When the counter reaches zero, the CountedEvent will signall it's event. The CallAllMethods will wait on that event.</p> <p>Another way is to use the WaitHandle array, but do a WaitForAny, and then process the results there until all handles are signalled. You can then use the AsyncState member to hold the callback delegate.</p> </blockquote> 2007-05-07T21:59:02-04:001699036http://forums.asp.net/p/1106663/1699036.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <blockquote><span class="icon-blockquote"></span> <h4>Svante</h4> <p></p> <blockquote><span class="icon-blockquote"></span> <h4>tompy_nation</h4> <font color="#008000" size="2"><font size="2">When i remove the last call, the errors occures on the new last one...</font></font></blockquote> <p></p> <p>One way to do this, is to make your own little CountedEvent class, which contains a ManualResetEvent, and a counter. Initialize an instance of this class with the counter value 12, pass the reference to the instance in the AsyncState member, and have each callback decrement the counter. When the counter reaches zero, the CountedEvent will signall it's event. The CallAllMethods will wait on that event.</p> <p></p> </blockquote> <p></p> <p>Do you have by any change an example of this solution cause i dont understand much off it [:&#36;] I'm just new to this assynchrounus calling...</p> 2007-05-07T22:02:27-04:001699435http://forums.asp.net/p/1106663/1699435.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>Something like this:</p> <pre class="prettyprint">public class CountedEvent { private int _count; private ManualResetEvent _event = new ManualResetEvent(false); public WaitHandle WaitHandle { get { return _event; } } private object _state; public object State { get { return _state; } } public CountedEvent(int count, object state) { _count = count; _state = state; } public void Decrement() { if (Interlocked.Decrement(ref _count) == 0) { _event.Set(); } } } private void CallAllMethods() { CountedEvent countedEvent = new CountedEvent(12, srv); srv.BeginGetServices(new AsyncCallback(WsCallbackServices), countedEvent); srv.BeginGetMemory(new AsyncCallback(WsCallbackMemory), countedEvent); // etc... countedEvent.WaitHandle.WaitOne(); } private void WsCallbackServices(IAsyncResult ar) { CountedEvent countedEvent = ar.AsyncState as CountedEvent; LokaleService.BMI srv = countedEvent.State as LokaleService.BMI; services = new System.Collections.ArrayList(srv.EndGetServices(ar)); countedEvent.Decrement(); }</pre> <p>&nbsp;</p> <p>It's kind of quick and dirty. Probably you want to implement an Increment method as well, and call that before each Begin-call instead of fixing at magic number '12'. In this case you still want to initialize the counter to '1', to guard against premature signalling and perform the matching Decrement just before entering the wait.</p> 2007-05-08T05:15:10-04:001699702http://forums.asp.net/p/1106663/1699702.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>well, i got everything like you said now, But i'm still getting the Error: The request failed with HTTP status 403: Access Forbidden.</p> <p>But this error is only showing when the webservice response slow... when it goes fast there are no errors...</p> <p>Would the increment method fix this problem?</p> 2007-05-08T08:21:19-04:001699782http://forums.asp.net/p/1106663/1699782.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished I dont think so, but a quick test is to initialize the counter to 13, and then add an additional decrement just before the wait. 2007-05-08T09:22:37-04:001699814http://forums.asp.net/p/1106663/1699814.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished nope that doesnt solve it, still the 403: Access Forbidden 2007-05-08T09:50:41-04:001699865http://forums.asp.net/p/1106663/1699865.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished Then you probably need to go the the server responding the requests and see what it's problem is. You might also try using fiddler or a similar tool listen to the HTTP-traffic and see what actually happens. Unless there are are other factors I'm not thinking about, it's probably not a concurrency-related problem any more. 2007-05-08T10:28:06-04:001700010http://forums.asp.net/p/1106663/1700010.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished <p>sometimes i receive the :</p> <p>The underlying connection was closed: An unexpected error occurred on a receive.</p> <p>instead off the HTTP status code: 403</p> 2007-05-08T12:26:24-04:001700025http://forums.asp.net/p/1106663/1700025.aspx/1?Re+execute+1+method+after+another+method+has+finishedRe: execute 1 method after another method has finished Oops. Are you also implementing the methods being called? If so, we might want to concentrate on that side of the business... A really long shot is if the webservices depend on a database, and they leak the database connection. That will actually seem to work as long as the load is light - but throwing 12 requests at it at once can trigger a problem caused by such a situation. 2007-05-08T12:34:58-04:00