异步死锁?

Joe*_*Joe 8 .net c# async-await

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

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

收到文件的作品:

[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;
}
Run Code Online (Sandbox Code Playgroud)

全部以下列内容开始:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

一切似乎都在起作用,除了PostAsync永远不会识别task已经返回的东西.我可以看到await ... PostAsync ...任务的状态是WaitingForActivation,但我不完全确定这意味着什么(记住,我对这个东西是个n00b).我的文件保存到正确的位置,但应用程序从不识别我的服务响应.

如果有人能指出我正确的方向,我将不胜感激.

nos*_*tio 6

我认为问题在于你只是UploadToService在里面瞎扯一下Page_Load.请求处理在此任务完成之前结束.

您应该<%@ Page Async="true" ...>在此WebForms页面中使用并包含<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))));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

file.InputStream.CopyTo(memoryStream);
Run Code Online (Sandbox Code Playgroud)

像这样:

await file.InputStream.CopyToAsync(memoryStream);
Run Code Online (Sandbox Code Playgroud)

并替换ContinueWithasync/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
    };
}
Run Code Online (Sandbox Code Playgroud)

相关:"在ASP.NET 4.5中使用异步方法".