0

私は 1 つの Web ページ MyWebPage.aspx を持っています。これは、ロード中に 2 つの Web サービスからのデータを独自のアルゴリズムとともに表示する必要があります。

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

上記の例の問題は、ページが 5 秒後に読み込まれるため、MyLabelI と MyLabelII Text が設定されないことです。

EventLog への書き込みでチェックされるように、両方の End メソッドが正しく呼び出されます。これを解決するにはどうすればよいですか...「すべてが一度に開始され、すべてが完了するまで待機します...」のようなものです。実行中のスレッドが 5 秒以上待機すると、必要に応じてコードが実行されることを理解しています..

AsyncWaitHandle の使用方法...

4

1 に答える 1

0

さて、この問題の答えは「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;
}
}

動作します:)コードは、一般的なリファクタリングで汎用にすることができます...

ただし、この種の設計を計画するときは注意してください...内部的には、スレッドプールのスレッドも使用する必要があります

ただ...私は深く掘り下げていません..しかし、そうでなければなりません..したがって、タスクが予定よりも長くかかる場合、およびそのようなタスクが複数ある場合

同時に発生すると、Web サーバーが影響を受け、ユーザーがタイムアウトする可能性があります...

25秒が55秒であることが判明した場合、ユーザーはとにかくタイムアウトするため、上記の欠陥にもかかわらず、私はまだこの前進を続けています

数秒...何人かのユーザーが作業できる状況の方が、まったく作業できないよりはましです..

より良い代替案があれば、投稿してください。

于 2011-12-01T12:38:16.930 に答える