WP7 + Ожидание завершения операции перед продолжением - PullRequest
3 голосов
/ 08 июня 2011

У меня есть приложение для Windows Phone 7, которое использует Silverlight с C #.Это приложение имеет метод, который запускает несколько запросов веб-службы.В другом месте моего кода у меня есть код, который выглядит следующим образом:

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

// Proceed

Как заставить мой пользовательский интерфейс "ждать" небольшое количество времени, не блокируя пользовательский интерфейс, а затем проверитьеще раз, чтобы увидеть, если мои вызовы веб-службы сделаны?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 13 июня 2011

Ответ заключается не в том, чтобы заставить пользовательский интерфейс вообще ждать, а в том, чтобы «идти с (асинхронным) потоком».

В конечном счете, асинхронная работа в C # 5 решит эту конкретную проблему,но пока нет времени для его выпуска для настольной CLR, не говоря уже о Silverlight или WP7.

Я лично рекомендовал бы изучить Microsoft.Phone.Reactive, которая является версией Reactive Extensions (Rx) для WP7 и поставляется сSDK.Это довольно большой вопрос, который требует достаточно много времени, чтобы разобраться, но он действительно может упростить вашу работу с асинхронными сценариями.

Предполагая, что каждая из ваших веб-служб возвращает разные типы данных, я бы:

  • Оберните каждый вызов веб-службы в IObservable 1
  • Используйте Do для «просмотра» сообщения и выполнения побочных эффектов (например, назначениязначение локально)
  • Используйте Select, чтобы "нормализовать" типы, чтобы они все были одного типа (требуется для следующего шага)
  • Используйте ForkJoin для выполнения каждого изпараллельные запросы и их обработка после завершения каждого

1 Создание IObservable для вашего запроса действительно зависит от того, какой асинхронный шаблон вы используете.Предполагая, что вы используете WebClient, вот метод расширения, который создает Observable из DownloadStringAsync в качестве образца (он может выглядеть сложным, но он просто обрабатывает ошибки и отмены):

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 + "нормализующие" шаги, потому что все мои типы данных одинаковы (String).Таким образом, я могу подписаться на них все в виде массива (это тонкость работы 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 голос
/ 08 июня 2011

Вы должны использовать метод асинхронного обратного вызова и обрабатывать видимость индикатора выполнения события обратного вызова.

Используя , в то время как , вы заставляете пользовательский интерфейс ждать потокбыть исполненным.

Я использовал этот метод в своем блоге здесь: http://www.infopoint.com/News-Events/EntryId/29/Building-a-WP7-RSS-reader-Part-1-Basics.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...