2016-03-23 3 views
0

ネットワーク上でasync/awaitを使うのが有益だと読んだので、ファイルを空白のブロブにアップロードするのにそれを適用したいと思います。Task.Wait()は私のアプリケーションをデッドロックします

この方法で.Wait()を使用すると、アプリケーションはawait _Container.CreateIfNotExistsAsync();で停止します。 InitializeCategories(context)メソッドは、ブロブがループする前にアップロードするのを待つ必要があるため、.Wait()を使用します。

私はマルチスレッドを使うのが全く新しいです、なぜこれが起こっているのか説明して、それを修正する方法を教えてもらえますか?

protected override void Seed(ApplicationDbContext context) 
{ 
    base.Seed(context); 

    InitializeImages().Wait(); 
    InitializeCategories(context); 
} 

public static async Task InitializeImages() 
{ 
    _PlaceHolderImage = "placeholder-categories.jpg"; 
    _StorageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString")); 
    _BlobClient = _StorageAccount.CreateCloudBlobClient(); 
    _Container = _BlobClient.GetContainerReference("images"); 

    await _Container.CreateIfNotExistsAsync(); 

    //To view the blob in the browser 
    await _Container.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); 

    CloudBlockBlob blockBlob = _Container.GetBlockBlobReference(_PlaceHolderImage); 
    await blockBlob.UploadFromFileAsync(HttpContext.Current.Server.MapPath("~/Content/Images/" + _PlaceHolderImage), FileMode.Open); 
} 

public static void InitializeCategories(ApplicationDbContext db) 
{ 
    // Loop over items within the container and output the length and URI. 
    foreach (IListBlobItem item in _Container.ListBlobs()) 
    { 
     if (item.GetType() == typeof(CloudBlockBlob)) 
     { 
      CloudBlockBlob blob = (CloudBlockBlob)item; 

      Console.WriteLine("Block blob of length {0}: {1}", blob.Properties.Length, blob.Uri); 
     } 
    } 
} 
+0

保護オーバーライドvoidシード(ApplicationDbContextコンテキスト)の署名を保護オーバーライド非同期タスクシード(ApplicationDbContext)に変更することはできますか?その後、InitializeImages()を待ち、Wait()呼び出しを取り除くことができます。 –

+0

@Jeroen私がそれを変更した場合、署名は一致しません。ベースメソッドは外部ライブラリにありますので、変更することはできません。 –

+0

この行を 'await_Container.CreateIfNotExistsAsync();'に変更してみてください '_Actit _Container.CreateIfNotExistsAsync()。ConfigureAwait(false);' –

答えて

3

私は/

はい、しかしなぜネットワーキングに待つ非同期を使用することが有益であることを読んだことがありますか?

答えはasyncです(特にI/Oベースのコードの場合)。スレッドを解放して他のことを行うことができます。 ASP.NETアプリケーションでは、着信要求を処理するために利用できるスレッドがさらにあることを意味します。彼らは後まで何もすることができなくなりますので、アプリケーションがその最初の要求を処理する(とDBを播種)されたときああ、...

protected override void Seed(ApplicationDbContext context) 

を待って、スレッドを解放内の任意の点はありませんとにかくdbに種が掛けられる。

このような状況では、同期してアップロードするだけです。デフォルトで

  • awaitは「コンテキスト」をキャプチャします、そして:これは

    が起こっている理由

    は、誰かが私が詳細に入るblog postを持っていますが、要約する説明することができますそのコンテキストでasyncメソッドの実行を再開します。

  • ASP.NETは現在、HttpContext.Current、現在のページカルチャなどを処理するリクエストコンテキストを持っています。
  • ASP.NETコンテキストでは、一度に1つのスレッドしか使用できません。

あなたが要求コンテキスト(Wait)でスレッドをブロックしたときに、自由であるためにその要求コンテキストを待っているためこのように、async方法は完了することはできません。もちろん、Waitasyncメソッドが完了するのを待っているので、デッドロックが発生します。

+0

あなたのブログの投稿は素晴らしく、多くの助けとなりました。しかし、「文脈」を指しているときはどういう意味ですか? –

+0

コンテキストが 'SynchronizationContext.Current'で、' null'でなければコンテキストは 'TaskScheduler.Current'です。この場合、 'AspNetSynchronizationContext'のインスタンスである' SynchronizationContext.Current'です。 –

関連する問題