【问题标题】:How to access initial parameters in the callback of an asynchronous WCF request?如何在异步 WCF 请求的回调中访问初始参数?
【发布时间】:2011-08-29 07:28:56
【问题描述】:

我目前正在更新一个使用 WCF Web 服务的客户端应用程序,从同步调用到异步调用。主服务器和客户端在同一个本地网络上,但是应用程序在等待响应时挂起太不可靠了。

应用程序在 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));
                    }
                }
            }
        }
    }

【问题讨论】:

    标签: c# .net wcf asynchronous


    【解决方案1】:

    如果MyClient 是生成的类,则应该调用第二个函数

    MyClient.GetUserInfoAsync(string fobID, object userState);
    

    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
    }
    

    【讨论】:

    • 正是我想要的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2015-05-03
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    相关资源
    最近更新 更多