2011-08-29 24 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