异步死锁?

时间:2014-07-22 05:07:37

标签: c# .net async-await

我相当肯定我在我的应用程序中创建了一个死锁,我不知道如何解决这个问题。我有一些活动部件,我是asyncawait的新手,所以请耐心等待。

我有一个上传文件的客户端如下:

public static async Task<string> UploadToService(HttpPostedFile file, string authCode, int id)
{
    var memoryStream = new MemoryStream();
    file.InputStream.CopyTo(memoryStream);

    var requestContent = new MultipartFormDataContent();
    var fileContent = new ByteArrayContent(memoryStream.ToArray());
    fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(file.ContentType);
    requestContent.Add(fileContent, "file", file.FileName);

    using (var httpClient = new HttpClient())
    {
        httpClient.BaseAddress = new Uri(BaseUrl);
        httpClient.DefaultRequestHeaders.Accept.Clear();

        var message =
            await
                httpClient.PostAsync(
                    string.Format("Upload?authCode={0}&id={1}", authCode, id),
                    requestContent);

        return await message.Content.ReadAsStringAsync();
    }
}

收到档案的作品:

[HttpPost]
public Task<HttpResponseMessage> Upload(string authCode, int id)
{
    var request = Request;

    var provider = new CustomMultipartFormDataStreamProvider(root);

    var task =
        request.Content.ReadAsMultipartAsync(provider)
            .ContinueWith(o =>
            {
                // ...
                // Save file
                // ...

                return new HttpResponseMessage()
                {
                    Content = new StringContent("File uploaded successfully"),
                    StatusCode = HttpStatusCode.OK
                };
            });

    return task;
}

以下内容全部启动:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        var file = HttpContext.Current.Request.Files[0];

        var response = UploadToService(file, hiddenAuthCode.Value, int.Parse(hiddenId.Value));
    }
}

除了PostAsync永远不会识别出task已被退回之外,所有内容似乎都有效。我可以看到await ... PostAsync ...任务的状态是WaitingForActivation,但我不完全确定这意味着什么(记住,我对这个东西是个n00b)。我的文件保存到正确的位置,但应用程序从不识别我服务的响应。

如果有人能指出我正确的方向,那将非常感激。

1 个答案:

答案 0 :(得分:6)

我认为问题在于您只需在UploadToService内以一种即兴发射的方式呼叫Page_Load。请求处理在此任务完成之前结束。

您应该在此WebForms页面中使用<%@ Page Async="true" ...>,并在<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />中添加web.config

然后使用RegisterAsyncTask,代码如下所示:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        var file = HttpContext.Current.Request.Files[0];

        RegisterAsyncTask(new PageAsyncTask(() => UploadToService(file, 
            hiddenAuthCode.Value, int.Parse(hiddenId.Value))));
    }
}

另一方面,您可以改进这一部分:

file.InputStream.CopyTo(memoryStream);
像这样:

await file.InputStream.CopyToAsync(memoryStream);

并将ContinueWith替换为async/await

[HttpPost]
public async Task<HttpResponseMessage> Upload(string authCode, int id)
{
    var request = Request;

    var provider = new CustomMultipartFormDataStreamProvider(root);

    await request.Content.ReadAsMultipartAsync(provider);

    return new HttpResponseMessage()
    {
        Content = new StringContent("File uploaded successfully"),
        StatusCode = HttpStatusCode.OK
    };
}

相关:"Using Asynchronous Methods in ASP.NET 4.5"