Вопрос по windows-runtime, c# – FileIO.ReadTextAsync иногда зависает

2

Я просто экспериментирую с WinRT и одним демонстрационным приложением, которое я создаю, - это базовый «блокнот». приложение стиля, которое загружает / сохраняет в локальное хранилище. Пока я знаком сasync подход для создания приложений WinRT, мое демонстрационное приложение использует синхронныйLoad чтобы все было просто.

Проблема заключается в том, что когда звонятLoadработает 2 раза из 3, а остальное время приложение зависает на вызовеvar result = await FileIO.ReadTextAsync(storageFile);

public class ContentStorage : IContentStorage
{
    private const string FileName = "contents.txt";

    public string Load()
    {
        return LoadAsync().Result;
    }

    public void Save(string content)
    {
        SaveAsync(content);
    }

    private static async Task<string> LoadAsync()
    {
        var storageFile = await LocalFolder.GetFileAsync(FileName);
        var result = await FileIO.ReadTextAsync(storageFile);

        return result;
    }

    private static async void SaveAsync(string content)
    {
        var storageFile = await LocalFolder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);

        FileIO.WriteTextAsync(storageFile, content);
    }

    private static StorageFolder LocalFolder
    {
        get { return ApplicationData.Current.LocalFolder; }
    }
}

Я делаю что-то необычайно глупое здесь?

FWIW, я экспериментировал с изменениемLoad просто явно блокировать на каждом шаге, и это улучшает зависание до 1 из 20, но я все еще не понимаю, почему оно вообще зависает ...

public string Load()
{
    var storageFile = LocalFolder.GetFileAsync(FileName).AsTask().Result;
    var result = FileIO.ReadTextAsync(storageFile).AsTask().Result;

    return result;
}
Ганс, пропуская факт отсутствия ключевого слова awaits перед WriteTextAsync, что делаетload не работать, как ожидалось? rodrigoelp
Вы не делаете ничего, чтобы гарантировать, что WriteTextAsync () завершается. Плохая идея. Hans Passant

Ваш Ответ

2   ответа
4

async approach for building WinRT apps, my demo app is using a synchronous Load to keep things simple.

На самом деле, нет. Смешивание синхронного с асинхронным кодом чрезвычайно сложно. Гораздо проще просто использоватьasync везде.

Когдаasync Метод продолжает выполнение после ожидания задачи, по умолчанию он возвращается в исходный контекст. (Я расскажу об этом более подробно в моемasync/await blog post). Некоторые контексты (такие как контексты пользовательского интерфейса) допускают только один поток; если этот поток заблокирован (например, наTask.Result), тоasync Метод не может войти в этот контекст, чтобы завершить его выполнение. Это вызывает тупик.

Для дополнительной информации:

The async/await FAQ has a lot of detail on the context capture and resume. Stephen Toub on the Parallel Team Blog has another blog post Await, and UI, and deadlocks! Oh, my!, which explains this particular deadlock situation in detail. I wrote an exhaustive answer for this kind of deadlock in an MSDN forum post.

Этот тупик достаточно известен, так что он фактически был демо-версией Microsoft:

By Stephen Toub at the BUILD conference (Sept 16, 2011). By Lucian Wischik at DevConnections (Mar 26, 2012).
0

ConfigureAwait(false) с операцией ожидания, может бытьReadTextAsync не является потокобезопасным, поэтому он повесит поток пользовательского интерфейса, когда ожидание завершится и вернется к потоку пользовательского интерфейса.

Похожие вопросы