Task.Wait()使我的应用程序死锁

时间:2016-03-23 18:57:40

标签: c# asp.net-mvc multithreading azure

我已经读过在网络上使用async / await是有益的,所以我想将它应用于将文件上传到azure blob。

当我在方法上使用.Wait()时,应用程序会在await _Container.CreateIfNotExistsAsync();上停止。我想使用.Wait(),因为InitializeCategories(context)方法需要等待blob上传才能循环播放。

我对使用多线程完全陌生,有人可以解释为什么会发生这种情况并告诉我如何修复它吗?

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);
        }
    }
}

1 个答案:

答案 0 :(得分:3)

  

我已经读过在网络上使用async / await是有益的

是的,但是为什么

答案是:async是有益的(特别是对于基于I / O的代码),这样你就可以释放线程做其他事情。在ASP.NET应用程序中,这意味着您有更多线程可用于处理传入请求。哦,等等......

protected override void Seed(ApplicationDbContext context)

当你的应用程序正在处理它的第一个请求(以及播种数据库)时,没有任何一点可以释放线程,因为他们无法做任何事情,直到数据库被播种为止。

所以在这种情况下,你应该只是同步上传。

  

有人可以解释为什么会这样吗

我有一个更详细的blog post,但总结一下:

    默认情况下,
  • await会捕获"上下文",并将在该上下文中继续执行async方法。
  • ASP.NET(当前)有一个请求上下文,用于处理HttpContext.Current,当前页面文化等内容。
  • ASP.NET上下文一次只允许一个线程。

因此,当您在请求上下文(Wait)中阻塞某个线程时,async方法无法完成,因为它正在等待该请求上下文空闲。当然,Wait正在等待async方法完成,因此您最终会遇到死锁。