【问题标题】:Silverlight Async Design Pattern IssueSilverlight 异步设计模式问题
【发布时间】:2010-05-06 18:24:52
【问题描述】:

我在 Silverlight 应用程序的中间,我有一个需要调用 web 服务的函数,并使用结果完成其余的函数。

我的问题是我通常会做一个同步的 Web 服务调用得到结果并使用该函数进行。由于 Silverlight 不支持没有其他自定义类来模仿它的同步 Web 服务调用,我认为最好采用异步流程而不是与之抗衡。所以我的问题与在程序流中处理异步调用的最佳设计模式有关。

在以下示例中,我想根据 Web 服务调用的返回值使用 myFunction TypeId 参数。但是在调用此函数之前,我不想调用 Web 服务。如何更改我的代码设计以允许异步调用?

        string _myPath;

    bool myFunction(Guid TypeId)
    {
        WS_WebService1.WS_WebService1SoapClient proxy = new WS_WebService1.WS_WebService1SoapClient();
        proxy.GetPathByTypeIdCompleted += new System.EventHandler<WS_WebService1.GetPathByTypeIdCompleted>(proxy_GetPathByTypeIdCompleted);
        proxy.GetPathByTypeIdAsync(TypeId);

        // Get return value

        if (myPath == "\\Server1")
        {
            //Use the TypeId parameter in here
        }
    }

    void proxy_GetPathByTypeIdCompleted(object sender, WS_WebService1.GetPathByTypeIdCompletedEventArgs e)
    {
        string server = e.Result.Server;
        myPath = '\\' + server;
    }

提前致谢, 迈克

【问题讨论】:

    标签: silverlight design-patterns asynchronous


    【解决方案1】:

    最好使用Reactive Extensions。然后(假设你要在 WS_WebService1SoapClient 上创建一个扩展方法 IObservable&lt;string&gt; GetPathByTypeId(string typeId) 你可以这样做:

    proxy
        .GetPathByTypeId(TypeId)
        .Subscribe(server => 
            { 
                //Here you can do stuff with the returned value
            });
    

    尽可能接近同步调用:)

    【讨论】:

    • 非常感谢我去看看
    【解决方案2】:

    鉴于 Silverlight 的异步特性,您无法从 myFunction 返回值。相反,您可以传递一个在服务调用完成后执行的操作。请参阅下面的示例代码。我不确定它是否被认为是最佳实践,但我经常使用这种“模式”,它对我来说一直很好用。

    编辑
    更新了以下代码以在回调操作中包含多个参数。

    void DoSomething(Guid TypeId, Action<int, bool> Callback)
    {
        WS_WebService1.WS_WebService1SoapClient proxy = new WS_WebService1.WS_WebService1SoapClient();
        proxy.GetPathByTypeIdCompleted += (s, e) =>
            {
                string server = e.Result.Server;
                myPath = '\\' + server;
    
                //
                if (myPath == "\\Server1")
                {
                    Callback(888, true);
                }
                else
                {
                    Callback(999, false);
                }
            };
        proxy.GetPathByTypeIdAsync(TypeId);
    
    }
    
    void CallDoSomething()
    {
        DoSomething(Guid.NewGuid(), (returnValue1, returnValue2) =>
            {
                //Here you can do stuff with the returned value(s)
            });
    }
    

    【讨论】:

    • 这个例子对我来说似乎很不错,是否可以通过Action参数传递多个变量?示例:CallBack(true, myObject);谢谢。
    • 当然,我刚刚更新了上面的示例代码以包含一个 int 和一个 bool 作为参数。但是您可以将其更改为您需要的任何内容。
    【解决方案3】:

    将GetPathByTypeId结果的处理放到GetPathByTypeIdCompleted回调中。在那里分配 mypath 。将 mypath 设为属性并实现 INotifyPropertyChanged 接口以通知 Mypath 的依赖项 Mypath 已更改。

    1. 观察者依赖于 mypath
    2. 观察者为mypath设置通知事件
    3. 通过异步调用GetPathByTypeId获取Mypath
    4. Mypath 已设置,调用 Observer 的通知
    5. 观察者与 Mypath 一起使用

    【讨论】:

    • 我也有同样的想法,我已经实现了这个方法。没关系,但对我来说似乎不是很优雅。不过谢谢你的帮助。
    猜你喜欢
    • 2011-03-21
    • 1970-01-01
    • 2012-11-15
    • 2010-12-10
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多