【问题标题】:Async Deadlock?异步死锁?
【发布时间】:2014-09-12 19:10:42
【问题描述】:

我相当肯定我在我的应用程序中造成了死锁,但我不确定如何解决这个问题。我有一些活动部件,并且是 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)。我的文件已保存到正确的位置,但应用程序无法识别来自我的服务的响应。

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

【问题讨论】:

    标签: c# .net async-await


    【解决方案1】:

    我认为问题在于您只是在Page_Load 内以一种即发即弃的方式调用UploadToService。请求处理只是在此任务完成之前结束。

    您应该在此 WebForms 页面中使用&lt;%@ Page Async="true" ...&gt;,并在您的web.config 中包含&lt;add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /&gt;

    然后使用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".

    【讨论】:

    • 将其更改为RegisterAsyncTask 后,我得到Argument type System.Threading.Task.Task&lt;string&gt; is not assignable to parameter type System.Web.UI.PageAsyncTask。我尝试更改我的返回类型,但这导致了一些其他错误。有什么想法吗?
    • @Joe,再调整一下:new PageAsyncTask(() =&gt; UploadToService(file, ...)),参数是Func&lt;Task&gt;
    • 谢谢!进行更改后,不再出现死锁。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 2014-12-09
    相关资源
    最近更新 更多