WP7 +在继续之前等待操作完成

时间:2011-06-08 16:29:27

标签: c# silverlight windows-phone-7

我有一个使用Silverlight和C#的Windows Phone 7应用程序。此应用程序有一个方法可以触发多个Web服务请求。在我的代码中的另一点,我有一些代码如下所示:

myProgressBar.Visibility = Visibility.Visible;
while (AreWebServiceCallsDone() == false)
{
  // Need "waiting" code here
}

// Proceed

如何在不锁定用户界面的情况下让我的用户界面“等待”一小段时间,然后再次检查以查看我的网络服务是否已完成?

谢谢!

2 个答案:

答案 0 :(得分:2)

答案是不要让UI等待,而是“按照(异步)流程”进行操作。

最终,C#5中的异步内容将解决这一特定问题,但桌面CLR的发布没有时间表,更不用说Silverlight或WP7了。

我个人建议查看Microsoft.Phone.Reactive,它是Reactive Extensions(Rx)的WP7版本,并附带SDK。这是一个相当大的主题,需要花费大量时间来解决问题,但可以真正简化您处理异步方案的方式。

假设您的每个Web服务都返回不同类型的数据,我会:

  • 在IObservable 1
  • 中包装每个Web服务调用
  • 使用Do“查看”消息并执行副作用(例如在本地分配值)
  • 使用Select“规范化”类型,使它们的类型相同(下一步所需)
  • 使用ForkJoin并行执行每个请求,并在每个请求完成时进行处理

1 为您的请求创建IObservable实际上取决于您使用的异步模式。假设你正在使用WebClient,这里是一个扩展方法,它从DownloadStringAsync创建一个Observable作为样本(它可能看起来很复杂,但它只是处理错误和取消):

public static class ObservableWebClient
{
    public static IObservable<string> DownloadStringObservable(
        this WebClient webClient, Uri uri)
    {
        return Observable.Create(observer =>
        {
            var disposable = new CompositeDisposable();

            var completedObservable = Observable.FromEvent<
                    DownloadStringCompletedEventHandler, 
                    DownloadStringCompletedEventArgs
                >(
                    h => new DownloadStringCompletedEventHandler(h),
                    h => webClient.DownloadStringCompleted += h,
                    h => webClient.DownloadStringCompleted h= h
                );

            disposable.Add(completedObservable
                .SelectMany(ev =>
                {
                    return (ev.EventArgs.Error != null)
                        ? Observable.Throw<string>(ev.EventArgs.Error)
                        : Observable.Return(ev.EventArgs.Result);
                })
                .Subscribe(observer));

            disposable.Add(Disposable.Create(
                () => webClient.CancelAsync()));

            return disposable;
        });
    }
}

然后您可以这样使用它:

请注意,我已跳过Do +“规范化”步骤,因为我的数据类型都是相同的(字符串)。因此,我可以将它们全部订阅为一个数组(如果你想知道的话,这是ForkJoin如何工作的微妙之处)

var webClientA = new WebClient();
var webClientB = new WebClient();
var webClientC = new WebClient();

Observable.ForkJoin(
        webClientA.DownloadStringObservable(uriA),
        webClientB.DownloadStringObservable(uriB),
        webClientC.DownloadStringObservable(uriC),
    )
    .ObserveOnDispatcher()
    .Subscribe(dataArray =>
    {
        // All three have completed
        this.DataA = dataArray[0];
        this.DataB = dataArray[1];
        this.DataC = dataArray[2];
    });

答案 1 :(得分:1)

您应该使用异步回调方法并处理进度条对回叫事件的可见性。

使用 while ,您正在让UI等待线程执行。

我在我的博文中使用了这种方法:http://www.infopoint.com/News-Events/EntryId/29/Building-a-WP7-RSS-reader-Part-1-Basics.aspx

相关问题