2011-08-29 14 views
1

現在、WCF Webサービスを同期から非同期呼び出しに使用するクライアントアプリケーションを更新しています。メインサーバーとクライアントは同じローカルネットワーク上にありますが、応答を待つ間、アプリケーションがハングすることはあまりにも信頼できません。非同期WCF要求のコールバックで初期パラメータにアクセスする方法は?

アプリケーションは、2つのサーバー間で4つの同一のエンドポイントを使用します(インスタンスがクラッシュした場合や、サーバーがオフラインの場合でも、何かが呼び出されるはずです)。

クライアントには、Webサービスへの呼び出しを行うレイヤがあります。私の最初の同期設計はアクティブなエンドポイントを呼び出すためのものでした。例外がスローされた場合は、次のエンドポイントに移動し、同じメソッドを再帰的に呼び出します。これは、すべてのエンドポイントが使い果たされるまで行われます。

これを非同期にするための変更を加えましたが、1つの問題があります。コールバックに入るとパラメータは失われます。そのため、Beginメソッドを再帰的に呼び出すときには、パラメータを再度渡すことはできません。

Beginメソッドからコールバックメソッドにパラメータを渡す最も良い方法は何ですか?それらはクライアントオブジェクトのどこにでも保存されていますか?それは出来事を通してやってもいいですか、それともクラスレベルで保管すべきですか?

答えて

1
public delegate void GetUserInfoCompletedEventHandler(UserInfo e); 
    public static event GetUserInfoCompletedEventHandler GetUserInfoCompleted; 
    public delegate void GetUserInfoFaultedEventHandler(string errorMessage); 
    public static event GetUserInfoFaultedEventHandler GetUserInfoFaulted; 


     public static void BeginGetUserInfo(string fobID) 
    { 
     MyClient client = new MyClient(availableEndpoints[activeEndpointIndex].Name); 
     client.GetUserInfoCompleted += new EventHandler<GetUserInfoCompletedEventArgs>(client_GetUserInfoCompleted); 
     client.GetUserInfoAsync(fobID); 
    } 


static void client_GetUserInfoCompleted(object sender, GetUserInfoCompletedEventArgs e) 
    { 
     // Get the instance of the client 
     MyClient client = (MyClient)sender;  

     if (null == e.Error) 
     { 
      // Close the client instance if there was no error 
      try { client.Close(); } 
      catch { } 

      if ((null != GetUserInfoCompleted) && (null != e.Result)) 
      { 
       // Report as successful and raise the event 
       ServiceActionSuccessful(); 
       GetUserInfoCompleted(e.Result); 
      } 
     } 
     else 
     { 
      // Abort the client as there was an error 
      try { client.Abort(); } 
      catch { } 

      if (e.Error is FaultException<WebServiceError>) 
      { 
       FaultException<WebServiceError> fault = (FaultException<WebServiceError>)e.Error; 

       if (null != GetUserInfoFaulted) 
       { 
        // A fault occurred in the web service 
        GetUserInfoFaulted(fault.Detail.ErrorMessage); 
       } 
      } 
      else 
      { 
       // Assume this was problem in connection so test if there any more endpoints to attempt 
       bool isNextEndpointAvaialble = ServiceActionFailure(); 

       if (isNextEndpointAvaialble) 
       { 
        // If there are more endpoints to try, call the method to run again 
        BeginGetUserInfo(); // Need parameters here 
       } 
       else 
       { 
        if (null != GetUserInfoFaulted) 
        { 
         // No more endpoints to try 
         GetUserInfoFaulted(Errors.GetUserFriendlyMessage(e.Error)); 
        } 
       } 
      } 
     } 
    } 

MyClientが生成されたクラスである場合、第二の機能があるはずが

​​

と呼ばuserState引数の内容はclient_GetUserInfoCompletedによって受信のEventArgsでGetUserInfoCompletedEventArgs.UserStateプロパティにdirctly渡されます。

だから、このような何かを行うことができます:

public static void BeginGetUserInfo(string fobID) 
{ 
    MyClient client = new MyClient(availableEndpoints[activeEndpointIndex].Name); 
    client.GetUserInfoCompleted += new EventHandler<GetUserInfoCompletedEventArgs>(client_GetUserInfoCompleted); 
    client.GetUserInfoAsync(fobID, fobID); 
} 

static void client_GetUserInfoCompleted(object sender, GetUserInfoCompletedEventArgs e) 
{ 
    string fobID = e.UserState as string; 
    // handle the event here... 
} 

別の方法としては、イベントを処理するため、ラムダを使用することです:

public static void BeginGetUserInfo(string fobID) 
{ 
    MyClient client = new MyClient(availableEndpoints[activeEndpointIndex].Name); 
    client.GetUserInfoCompleted += (sender, args) => client_GetUserInfoCompleted(sender, args, fobID); 
    client.GetUserInfoAsync(fobID); 
} 

static void client_GetUserInfoCompleted(object sender, GetUserInfoCompletedEventArgs e, string fobID) 
{ 
    // access the additional parameter fobID here 
} 
+0

を私が探していたまさに。ありがとう! – Adam

関連する問題