Вызов нескольких служб WCF с использованием IAsyncResult и AsyncCallback - PullRequest
0 голосов
/ 30 ноября 2011

У меня есть одна веб-страница MyWebPage.aspx, которая при загрузке должна отображать данные двух веб-сервисов вместе со своим собственным алгоритмом.

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.

Теперь, когда я вызываю это синхронно, загрузка займет 10 + 10 + 5 = 25 секунд.

Итак, мне предложили «метод асинхронного вызова», т.е. используя IAsyncResult / AsyncCallback. Теперь то, что произойдет (должно) произойти, это то, что все будут вызваны одновременно, и страница загрузится максимум через 10 секунд.

Так что я называю их сейчас "Начать / Конец" ...

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());
}
}

Теперь проблема с приведенным выше примером заключается в том, что MyLabelI & MyLabelII Text никогда не устанавливаются, поскольку страница загружается через 5 секунд

и поток освобождается. Оба метода End вызываются правильно, что проверяется записью в EventLog. Как я могу решить это ... что-то вроде «Все начинается сразу, а потом все ждут, пока все не завершится ...» Я понимаю, что если мой исполняющий поток ждет в течение 5 секунд больше, то код выполняется так, как требуется.

Как мне использовать AsyncWaitHandle ...

1 Ответ

0 голосов
/ 01 декабря 2011

Что ж, ответом на эту проблему является класс "System.Web.UI.PageAsyncTask". Он разрешает асинхронные вызовы задач и ожидает

завершение в том же потоке. Также можно создать несколько задач и выполнить их параллельно. Пожалуйста, ознакомьтесь с документацией

для получения дополнительной информации ... Будет работать в Asp.Net 2.0 и выше.

Для нашей задачи выше ... Я ставлю «Мой алгоритм» как синхронизацию, а обе другие задачи - как асинхронную параллель. Поэтому моя страница займет 10 + 5

= 15 секунд для загрузки.

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;
}
}

Работает :) Код можно сделать общим с помощью общего рефакторинга ...

Пожалуйста, будьте осторожны при планировании такого рода дизайна, хотя ... Внутренне это также должно использовать потоки из пула потоков

только ... Я не копался глубоко .. но должно быть .. Так что, если задачи занимают больше времени, чем планировалось, и если несколько таких задач

подняться в то же время, тогда веб-сервер может пострадать, и пользователи могут получить время ...

Я все еще продолжаю продвигаться вперед, несмотря на вышеуказанный недостаток, так как мои пользователи все равно будут иметь тайм-аут, если 25 секунд окажутся 55

секунд ... Лучше иметь ситуацию, когда некоторые пользователи могут работать, а не никто ..

Если есть лучшая альтернатива, пожалуйста, напишите.

...