7

非同期デッドロックで立ち往生しており、それを修正するための正しい構文がわかりません。私はいくつかの異なる解決策を見てきましたが、何が問題を引き起こしているのかを完全に把握することはできません.

Parseをバックエンドとして使用し、ハンドラーを使用してテーブルに書き込もうとしています。私のハンドラーは次のようになります。

public class VisitorSignupHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        //Get the user's name and email address
        var UserFullName = context.Request.QueryString["name"].UrlDecode();
        var UserEmailAddress = context.Request.QueryString["email"].UrlDecode();

        //Save the user's information
        var TaskToken = UserSignup.SaveUserSignup(UserFullName, UserEmailAddress);
        TaskToken.Wait();
        ....

    }

    public bool IsReusable { get { return false; } }
}

次に、中間層を呼び出しています。

public static class UserSignup
{
    public static async Task SaveUserSignup(string fullName, string emailAddress)
    {
        //Initialize the Parse client with the Application ID and the Windows key
        ParseClient.Initialize(AppID, Key);

        //Create the object
        var UserObject = new ParseObject("UserSignup")
                            {
                                {"UserFullName", fullName},
                                {"UserEmailAddress", emailAddress}
                            };

        //Commit the object
        await UserObject.SaveAsync();
    }
}

これはで行き詰まっているようですがWait()Wait()タスクが完了するのを待つだけで、通常の操作に戻るという印象を受けました。これは正しくありませんか?

4

2 に答える 2

14

私のブログ最近の MSDN の記事で説明している一般的なデッドロックの問題が発生しています。

つまり、await既定asyncでは、キャプチャされた "コンテキスト" 内でメソッドが再開されます。ASP.NET では、一度に 1 つのスレッドのみがその "コンテキスト" に入ることができます。したがって、 を呼び出すとWait、そのコンテキスト内のスレッドがブロックされ、メソッドawaitを再開する準備ができたときに がそのコンテキストに入ることができなくなります。asyncしたがって、コンテキスト内のスレッドはWait(asyncメソッドが完了するのを待っている) でasyncブロックされ、メソッドはコンテキストが解放されるのを待ってブロックされます... デッドロック。

これを修正するには、「ずっと非同期」にする必要があります。この場合、HttpTaskAsyncHandler代わりにIHttpHandler次を使用します。

public class VisitorSignupHandler : HttpTaskAsyncHandler
{
  public override async Task ProcessRequestAsync(HttpContext context)
  {
    //Get the user's name and email address
    var UserFullName = context.Request.QueryString["name"].UrlDecode();
    var UserEmailAddress = context.Request.QueryString["email"].UrlDecode();

    //Save the user's information
    var TaskToken = UserSignup.SaveUserSignup(UserFullName, UserEmailAddress);
    await TaskToken;
    ....

  }
}
于 2013-07-25T13:54:00.900 に答える
1

問題は、同期コードと非同期コードを混在させていることです。これは実行できますが、注意が必要です。最善の策は、http ハンドラーも非同期にすることです。

public class VisitorSignupHandler : HttpTaskAsyncHandler
    {
        public override async Task ProcessRequestAsync(HttpContext context)
        {
           //Get the user's name and email address
           var UserFullName = context.Request.QueryString["name"].UrlDecode();
           var UserEmailAddress = context.Request.QueryString["email"].UrlDecode();

           //Save the user's information
           await UserSignup.SaveUserSignup(UserFullName, UserEmailAddress);
..

        }
    }
于 2013-07-25T14:00:38.763 に答える