2011-08-29 44 views
1

我目前正在更新一個客戶端應用程序,它使用WCF Web服務從同步到異步調用。主服務器和客戶端位於同一個本地網絡上,但在等待響應時應用程序掛起太不可靠。如何訪問異步WCF請求的回調中的初始參數?

該應用程序利用2個服務器上的4個相同的端點(所以如果一個實例崩潰或服務器脫機,應該仍然有東西可以調用)。

客戶端有一個負責調用Web服務的層。我最初的同步設計是爲了調用活動端點,如果拋出異常,我們將移動到下一個端點並遞歸地調用相同的方法。這將完成,直到所有端點都耗盡。

我已經做了修改,使這種異步,但有一個問題。一旦我們在回調中,參數就會丟失。因此,當它遞歸地再次調用Begin方法時,參數將無法再次傳入。

將參數從Begin方法傳遞給回調方法的最佳方式是什麼?它們是否存儲在客戶端對象的任何位置?它可以通過事件完成,還是應該將它們存儲在課堂級別?

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

回答

1

如果MyClient是生成的類,應該有稱爲

​​

的第二函數的參數userState的內容消法傳遞到由client_GetUserInfoCompleted接收的EventArgs的所述GetUserInfoCompletedEventArgs.UserState屬性。

所以你可以做這樣的事情:

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

另一種方法是使用lambda處理事件:

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