Click here to Skip to main content
15,885,435 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have one web page MyWebPage.aspx which while loading has to show data from two webservices along with it's own algorithm.

1) WebServiceI.SomeMethod() -> Takes 10 seconds aprx. to respond.
2) WebServiceII.SomeMethod() -> Takes 10 seconds aprx. to respond.
3) My Algorithm -> Takes 5 second aprx to respond.
Now,when I call this synchronously,this will take 10+10+5 = 25 seconds to load.

So,I was suggested "Asynchronous Calling Method",i.e. using IAsyncResult/AsyncCallback. Now what will(should) happen is that all will be called simultaneously and the page will load in max 10 seconds.

So I call them now in the "Begin/End" way...

public partial class MyWebPage : System.Web.UI.Page
{
WebServiceI WebServiceIObject = new WebServiceI();
WebServiceII WebServiceIIObject = new WebServiceII();

protected void Page_Load(object sender, EventArgs e)
{
//BeginSomeMethod(AsyncCallback callback, object asyncState)[<- Method Signature]
WebServiceIObject.BeginSomeMethod(OnEndGetWebServiceISomeMethodResult, null);


//BeginSomeMethod(AsyncCallback callback, object asyncState)[<- Method Signature]
WebServiceIIObject.BeginSomeMethod(OnEndGetWebServiceIISomeMethodResult, null);


/* My Algorithm 5 seconds*/
DataSet DS = GetDataSetFromSomeWhere();
MyGataGrid.DataSource = DS.tables[0];
MyGataGrid.DataBind();
/* My Algorithm 5 seconds*/


//System.Threading.Thread.Sleep(6000);
}

//Will be called after 10 seconds
void OnEndGetWebServiceISomeMethodResult(IAsyncResult asyncResult)
{
string WebServiceISomeMethodResult = WebServiceIObject.EndSomeMethod(asyncResult);
MyLabelI.Text = WebServiceISomeMethodResult;
//EventLog MyLog = new EventLog("Application"); MyLog.Source = "MySourceI";
//MyLog.WriteEntry(DateTime.Now.ToString());
}

//Will be called after 10 seconds
void OnEndGetWebServiceIISomeMethodResult(IAsyncResult asyncResult)
{
string WebServiceIISomeMethodResult = WebServiceIIObject.EndSomeMethod(asyncResult);
MyLabelII.Text = WebServiceIISomeMethodResult;
//EventLog MyLog = new EventLog("Application"); MyLog.Source = "MySourceII";
//MyLog.WriteEntry(DateTime.Now.ToString());
}
}
Now the issue with the above example is that MyLabelI & MyLabelII Text are never set because the page loads after 5 seconds

and thread is released.Both End Methods are called correctly as checked by writing to EventLog. How can I resolve this... something like "All start at once and then all wait till all are complete..." I understand that if my executing thread waits for 5 seconds more then the code executes as required..

How should I use AsyncWaitHandle...

Or is it simply not possible from server side coding??
Posted

1 solution

Well,The answer to this problem is "System.Web.UI.PageAsyncTask" class.It allows Asynchronous calls to tasks and waits for completion on the same thread.Also multiple tasks can be created and made to run parallel.Please go through the documentation for further information...Will work in Asp.Net 2.0 & Above Only.
For our problem above...I am putting "My Algorithm" as sync and both other tasks as Async parallel.So my page will take 10+5 = 15 seconds to load.

public partial class MyWebPage : System.Web.UI.Page
{
WebServiceI WebServiceIObject = new WebServiceI();
WebServiceII WebServiceIIObject = new WebServiceII();

protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask PAT_I = new PageAsyncTask
(BeginGetWebServiceISomeMethodResult, OnEndGetWebServiceISomeMethodResult, null, null, true);
Page.RegisterAsyncTask(PAT_I);
PageAsyncTask PAT_II = new PageAsyncTask
(BeginGetWebServiceIISomeMethodResult, OnEndGetWebServiceIISomeMethodResult, null, null, true);
Page.RegisterAsyncTask(PAT_II);
Page.ExecuteRegisteredAsyncTasks();

/* My Algorithm 5 seconds*/
DataSet DS = GetDataSetFromSomeWhere();
MyGataGrid.DataSource = DS.tables[0];
MyGataGrid.DataBind();
/* My Algorithm 5 seconds*/
}
IAsyncResult BeginGetWebServiceISomeMethodResult
(object Sender, EventArgs EventArgsObject,
AsyncCallback AsyncCallbackObject, object PassAnythingExtraIfRequired)
{
return WebServiceIObject.BeginSomeMethod(AsyncCallbackObject, PassAnythingExtraIfRequired);
}

IAsyncResult BeginGetWebServiceIISomeMethodResult
(object Sender, EventArgs EventArgsObject,
AsyncCallback AsyncCallbackObject, object PassAnythingExtraIfRequired)
{
return WebServiceIIObject.BeginSomeMethod(AsyncCallbackObject, PassAnythingExtraIfRequired);
}

void OnEndGetWebServiceISomeMethodResult(IAsyncResult asyncResult)
{
string WebServiceISomeMethodResult = WebServiceIObject.EndSomeMethod(asyncResult);
MyLabelI.Text = WebServiceISomeMethodResult;
}
void OnEndGetWebServiceIISomeMethodResult(IAsyncResult asyncResult)
{
string WebServiceIISomeMethodResult = WebServiceIIObject.EndSomeMethod(asyncResult);
MyLabelII.Text = WebServiceIISomeMethodResult;
}
}
Works :) The code can be made generic with common refactoring...
Please be careful while planning for this kind of design though...Internally this must also be using threads from threadpool only...I have not dug in deep..but must be..So if the tasks happen to take moretime than planned and if several such tasks get raised at the same time,then web server could suffer and users could get time out...
I am still carrying this forward inspite of above flaw as my users will time out anyway if 25 seconds turns out to be 55 seconds...Better to have a situation where some users are able to work rather than none..
If there is some better alternative,please post.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900