c# - 异步死锁?

标签 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();
    }
}

接收文件的piece:

[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 但我不完全确定那是什么意思(记住,我对这东西一窍不通)。我的文件已保存到正确的位置,但应用程序始终无法识别来 self 的服务的响应。

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

最佳答案

我认为问题在于您只需调用 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))));
    }
}

附带说明一下,您可以改进这部分:

file.InputStream.CopyTo(memoryStream);

像这样:

await file.InputStream.CopyToAsync(memoryStream);

并替换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
    };
}

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

关于c# - 异步死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24879340/

相关文章:

c# - 异步方法是否必须使用 "await"关键字?

javascript - 在 Node 版本 > 10 中,await 不会调用 Promise.then 方法

c# - 提高 WPF 列表框的绘制速度

c# - 从 RegisterStartupScript 转义字符的正确方法

c# - "The subprocess making the call can not access this object because the owner is another thread"异常异步/等待 WPF C#

c# - 使用 Entity Framework Core 编写计算成员

c++ - 未从 ASP.NET WebApi 中的 PATH 加载的 native DLL

javascript - 等待关键字在 Redux 操作中不起作用

c# - 为什么.NET 不将参数值添加到异常消息中,例如在 int.Parse 中

c# - 使用 ORM 的丰富域模型