1

次のようなメソッドがあります。

    static async Task<string> GetGooglePage(ProxyInfo proxy)
    {
        using (var m=new MyNetworkClass())
        {
            m.Proxy = proxy;
            return await m.GetAsync("http://www.google.com");
        }
    }

今、非同期ではないメソッドから呼び出して、結果を取得したいと考えています。

私がやろうとしていた方法は次のようなものです:

        foreach (var proxy in proxys)
        {
            try
            {
                GetGooglePage(proxy.ToProxyInfo()).Wait();
            }
            catch
            {}
            lock (Console.Out)
            {
                Console.Write(current++ + "\r");
            }
        }

私の問題は、時々GetGooglePage(proxy.ToProxyInfo()).Wait();デッドロックが発生することです (Visual Studio デバッガーによると、この呼び出しを超えるスタックはありません)。

までずっと async を使用したくありませんMain()GetGooglePageデッドロックの危険を冒さずに同期コードから正しく呼び出すにはどうすればよいですか?

4

2 に答える 2

4

私のブログで説明しているデッドロックに陥っています。

asyncすべての状況で機能する解決策がないため、メソッドをブロックするための標準的な解決策はありません。公式に推奨されている唯一の解決策はasync、ずっと使用することです。Stephen Toub は、ここで回避策の優れた要約を持っています。

async1 つの方法は、メソッドをバックグラウンド スレッドで ( 経由でTask.Run)実行してから、そのWait上で実行することです。このアプローチの欠点は次のとおりです。1)async特定のコンテキストを必要とするメソッド (たとえば、ASP.NET 応答への書き込み、UI の更新) では機能しません。2) 同期コンテキストから非同期スレッド プール コンテキストに変更すると、競合状態が発生する可能性があります。3) 別のスレッドを待っているだけのスレッドを燃やします。

もう 1 つの方法はasync、ネストされたメッセージ ループ内でメソッドを実行することです。このアプローチの欠点は次のとおりです。1) 「ネストされたメッセージ ループ」はプラットフォームごとに異なります (WPF と WinForms など)。2) ネストされたループは、再入可能性の問題を引き起こします (これは、Win32 時代の非常に多くのバグの原因でした)。

于 2013-08-31T21:57:13.787 に答える
2

最良の選択肢はこれを行わないことです。非同期メソッドを同期的に待機する場合、そもそもメソッドが非同期である理由はありません。したがって、(最上位のメソッドを同期させたい、または同期させなければならない場合) すべきことは、すべてのメソッドを同期させることです。

それができない場合は、次を使用してデッドロックを防ぐことができますConfigureAwait(false)

static async Task<string> GetGooglePage(ProxyInfo proxy)
{
    using (var m=new MyNetworkClass())
    {
        m.Proxy = proxy;
        return await m.GetAsync("http://www.google.com").ConfigureAwait(false);
    }
}

この方法では、メソッドが再開するときに、UI スレッドで再開しようとしないため、デッドロックが発生しません。awaitinまたはそれが呼び出すメソッドを使用している場合GetAsync()は、そこでも同じことを行う必要があります。

一般にConfigureAwait(false)、UI スレッドを再開する必要がない限り、どこでも使用することをお勧めします。

于 2013-08-31T21:57:33.417 に答える