2

私は WinRT を試しているところです。私が作成しているデモ アプリの 1 つは、ローカル ストレージにロード/保存する基本的な「メモ帳」スタイルのアプリです。私はasyncWinRT アプリを構築するための適切なアプローチに精通していますが、デモ アプリでは同期Loadを使用して物事をシンプルにしています。

問題は、 への呼び出しが行われるとLoad、3 回のうち 2 回は機能し、残りの時間はアプリが通話中にハングすることです。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各ステップで明示的にブロックするように変更して実験しましたが、これによりハングが 20 分の 1 に改善されましたが、なぜハングしているのかはまだわかりません...

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

    return result;
}
4

2 に答える 2

4

私はWinRTアプリを構築するための適切なアプローチに精通していasyncますが、私のデモアプリは同期Loadを使用して物事をシンプルにしています。

あまり。同期コードと非同期コードの混合は非常に複雑です。asyncどこでも使用する方がはるかに簡単です。

メソッドがタスクを待機した後も実行を継続するasyncと、デフォルトで元のコンテキストに戻ります。async(これについては、私の/awaitブログ投稿で詳しく説明します)。一部のコンテキスト(UIコンテキストなど)では、単一のスレッドのみが許可されます。そのスレッドがブロックされている場合(たとえば、on Task.Result)、asyncメソッドはそのコンテキストに入って実行を完了することができません。これにより、デッドロックが発生します。

詳細については:

このデッドロックは十分に有名であるため、実際にはMicrosoftによってデモが行われています。

于 2012-05-23T13:14:11.487 に答える
1

ConfigureAwait(false)をawait操作で使用してみてくださいReadTextAsync。スレッドセーフではない可能性があるため、awaitが終了するとUIスレッドがハングし、UIスレッドに戻ります。

于 2012-10-15T07:09:58.530 に答える