Асинхронный шаблон проектирования Silverlight - PullRequest
3 голосов
/ 04 мая 2010

Я нахожусь в центре приложения Silverlight, и у меня есть функция, которая должна вызывать веб-сервис и использовать результат для завершения остальной части функции.

Моя проблема в том, что я бы обычно делал синхронный вызов веб-службы, получал результат и использовал его, продолжая функцию. Поскольку Silverlight не поддерживает синхронные вызовы веб-служб без дополнительных пользовательских классов, имитирующих его, я думаю, что было бы лучше использовать асинхронный поток, чем бороться с ним. Поэтому мой вопрос касается того, каков наилучший шаблон проектирования для работы с асинхронными вызовами в потоке программы.

В следующем примере я хочу использовать параметр myFunction TypeId в зависимости от возвращаемого значения вызова веб-службы. Но я не хочу вызывать веб-сервис, пока не будет вызвана эта функция. Как я могу изменить свой дизайн кода, чтобы разрешить асинхронный вызов?

        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 голосов
/ 04 мая 2010

Лучше всего было бы использовать Reactive Extensions . Затем (при условии, что вы создадите метод расширения IObservable<string> GetPathByTypeId(string typeId) на WS_WebService1SoapClient, вы можете сделать это:

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

Как можно ближе к синхронному вызову:)

2 голосов
/ 04 мая 2010

Учитывая асинхронную природу Silverlight, вы не можете возвращать значения из myFunction. Вместо этого вы можете передать действие, которое выполняется после завершения вызова службы. Смотрите пример кода ниже. Я не уверен, считается ли это лучшей практикой, но я часто использую этот «шаблон», и он всегда работал для меня хорошо.

EDIT
Обновлен код ниже, чтобы включить несколько аргументов в действие обратного вызова.

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)
        });
}
1 голос
/ 04 мая 2010

Поместите обработку результата GetPathByTypeId в обратный вызов GetPathByTypeIdCompleted. Назначьте туда mypath. Сделайте свойство mypath свойством и реализуйте интерфейс INotifyPropertyChanged , чтобы уведомить зависимых от Mypath об изменении Mypath.

  1. Наблюдатель зависит от mypath
  2. Observer устанавливает событие уведомления для mypath
  3. Получить Mypath с помощью асинхронного вызова GetPathByTypeId
  4. Mypath установлен, вызывает уведомление Observer
  5. Обозреватель работает с Mypath
...