views:

292

answers:

2

Hello guys. I've got strange issue. I want wait end async call at sync function call. At other projects I successfully use ResetEvents, but in sl it don't seem to be working.

    //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;
    }

This method isn't work too:( Help please. What's wrong?

A: 

Just as:-

even * odd = even

so also:

async * sync = async.

You are attempting to make async * sync = sync and that is what is tripping you up. As soon as you add an asynchronous operation to a sequence the whole sequence becomes asynchronous. If you can get your outer SaveValue operation to accept that it is asynchronous then things can work better.

Since the code will follow quite divergent paths depending on whether encrypted is true or not then there really ought to be two versions of SaveValue.

For example:-

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
}

In this version the first SaveValue is synchronous whereas the second which does the encrypting is asynchronous and will call the doneCallback when complete. This call back allows this asynchronous version of SaveValue to participate in a further sequence of asynchronous operations.

AnthonyWJones
+1  A: 

The problem comes from the fact that in SL all service calls are made on the UI thread. So you have one method trying to sleep on the UI thread, waiting on a callback that has to happen on the UI thread.

It is impossible to create a truly synchronous call in SL. If you really want to work with things in an synchronous fashion take a look at Caliburn. He uses some cool co-routine patterns to simulate synchronous programming while leaving the actual service calls async.

Stephan