Silverlight. Ожидание завершения асинхронного метода в методе синхронизации - PullRequest
1 голос
/ 18 мая 2010

У меня странная проблема. Я хочу дождаться завершения асинхронного вызова при вызове функции синхронизации. В других проектах я успешно использую ResetEvents, но в sl он не работает.

    //Sync call save some value in storage
    public static void SaveValue(string key, object value, bool encrypted)
    {
        if (encrypted)
        {
            isEncrypting = true;
            var Registrator = new RegistratorClient();
            Registrator.EncryptCompleted +=Registrator_EncryptCompleted;
            Registrator.EncryptAsync(obj); //async call
            while (isEncrypting)
                 Thread.Sleep(10); 
            return;
        }
        ...
    }
    static void Registrator_EncryptCompleted(object sender, EncryptCompletedEventArgs e)
    {
        if (String.IsNullOrEmpty(fieldToSave))
            return;
        App Appvars = Application.Current as App;
        if (Appvars.Settings.Contains(fieldToSave))
            Appvars.Settings[fieldToSave] = e.Result;
        else
            Appvars.Settings.Add(fieldToSave, e.Result);
        isEncrypting = false;
    }

Этот метод тоже не работает :( Помогите, пожалуйста. Что не так?

Ответы [ 2 ]

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

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

Невозможно создать действительно синхронный вызов в SL. Если вы действительно хотите работать с вещами синхронно, взгляните на Caliburn . Он использует несколько классных шаблонов сопрограмм для симуляции синхронного программирования, оставляя фактические вызовы служб асинхронными.

0 голосов
/ 18 мая 2010

Так же, как: -

четный * нечетный = четный

так же:

async * sync = async.

Вы пытаетесь сделать async * sync = sync, и это то, что вас сбивает с толку. Как только вы добавляете асинхронную операцию в последовательность, вся последовательность становится асинхронной. Если вы можете заставить свою внешнюю операцию SaveValue признать, что она асинхронная, тогда все может работать лучше.

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

Например: -

public static void SaveValue(string key, object value)
{
    App Appvars = Application.Current as App;
    if (Appvars.Settings.Contains(key))
        Appvars.Settings[key] = value;
    else
        Appvars.Settings.Add(key, value);
}

public static void SaveValue(string key, object value, Action doneCallback)
{

    var Registrator = new RegistratorClient();
    Registrator.EncryptCompleted += (s, args) =>
    {
         // Really should consider some exception handling here.
         SaveValue(key, s.Result);
         if (doneCallback != null)
             doneCallback();
    }
    Registrator.EncryptAsync(value); //async call
}

В этой версии первый SaveValue является синхронным, тогда как второй, который выполняет шифрование, является асинхронным и по завершении вызовет doneCallback. Этот обратный вызов позволяет этой асинхронной версии SaveValue участвовать в дальнейшей последовательности асинхронных операций.

...