Silverlight异步设计模式问题

3
我正在进行一项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;
    }

感谢您的提前帮助, Mike
3个回答

3
最好使用Reactive Extensions。然后(假设您在WS_WebService1SoapClient上创建了一个扩展方法IObservable<string> GetPathByTypeId(string typeId)),您可以这样做:
proxy
    .GetPathByTypeId(TypeId)
    .Subscribe(server => 
        { 
            //Here you can do stuff with the returned value
        });

尽可能接近同步调用的效果 :)

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

编辑
已更新以下代码,以在回调操作中包括多个参数。
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);谢谢。 - Mike Mengell
当然,我刚刚更新了上面的示例代码,以包括 int 和 bool 作为参数。但你可以根据需要进行更改。 - Henrik Söderlund

1

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

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

我也想到了同样的方法并且已经实现了。虽然可以,但是对我来说似乎不太优雅。还是非常感谢你的帮助。 - Mike Mengell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接