Сохранение данных во время метода OnSuspending

Для приложения Windows 8 в C/XAML мне нужно сохранить некоторые данные в папку LocalState. Я думаю, у меня есть некоторые проблемы с использованием оператора async/await.

Когда я сохраняю данные во время работы приложения, все работает нормально, но когда я пытаюсь сохранить данные во время метода OnSuspending, кажется, что мое приложение не ждет завершения моего метода сохранения, чтобы приостановить приложение.

Самое странное, что когда я медленно отлаживаю и выполняю все операции шаг за шагом, все работает нормально, но когда я не ставлю никаких точек останова, приложение закрывается до сохранения данных.

Вот мой код:

    private async void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        await  api.BeforeClosing(true);
        deferral.Complete();
    }

    public async Task BeforeClosing(Boolean toTombstoning)
    {
            SaveItem<LoadingProgress>(fileNameLoadingProgress, InitLoading);
    }


    public static async void SaveItem<T>(String fileName, T data, Boolean crossThreadSecure = false) where T : IBinarySerializable
    {

            await CreateNewStorageFile(fileName);

            StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
            StorageFolder dataFolder = await localFolder.GetFolderAsync("Data");

            StorageFile file = await dataFolder.GetFileAsync(fileName);

            using (var stream = await file.OpenStreamForWriteAsync())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write<T>(data);
                }
            }
    }

    public async static Task CreateNewStorageFile(string filename)
    {
        StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
        StorageFolder dataFolder = await localFolder.CreateFolderAsync("Data", CreationCollisionOption.OpenIfExists);
        storage = await dataFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
    }

Я делаю что-то не так с оператором await? Или есть максимальное количество времени, когда мы можем выполнить некоторые операции, прежде чем приостановить приложение?

Спасибо

РЕДАКТИРОВАТЬ: я сделал несколько новых тестов: если я удалю deferral.Complete(); из метода OnSuspending он хорошо сохраняет данные (но, очевидно, никогда не закрывает приложение...). Я действительно думаю, что проблема в том, что у меня заканчивается время, когда приложение приостанавливается. Это действительно похоже на проблему в этом потоке: StorageFolder.CreateFileAsync аварийно завершает работу при вызове из App.OnSuspending. Но я пробовал все решения этого вопроса, и у меня все еще есть проблема...


person Thomas Salandre    schedule 31.08.2012    source источник


Ответы (2)


Ваша проблема в том, что вы звоните Complete до того, как все ваши async операции завершены.

Самое простое решение — сделать SaveItem методом async Task вместо async void, а затем await в BeforeClosing.

Как правило, методы async всегда должны возвращать Task/Task<T>, если только они необходимы возвращать void (например, обработчики событий).

person Stephen Cleary    schedule 31.08.2012
comment
Спасибо большое. Я, конечно, думал, что если метод асинхронный, он будет выполняться асинхронно, используя слово await, но я забыл использовать переменную Task... - person Thomas Salandre; 31.08.2012

Короткий и неожиданный ответ заключается в том, что OnSuspending — ненадежное место для любой критической логики сохраняемости приложения. По какой-то причине Microsoft приняла решение задержать событие OnSuspending на 5-10 секунд после закрытия приложения. Если приложение повторно запускается до этого события, создается отдельный экземпляр приложения, и оно не знает о том, что все еще находится в процессе приостановки.

Я пришел к такому выводу после того, как столкнулся с проблемами после, казалось бы, очень простых примеров в проекте WinRT Application Data Sample: http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2. После некоторого разочарования я нашел тему в MSDN, в которой OnSuspending обсуждается как триггер для сохранения: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/43da2212-9910-461d-816a-94b479ce9885/. Суть этой темы в том, что вы должны сохранять как можно чаще и чаще, потому что OnSuspending ненадежен.

person nelsestu    schedule 22.01.2013