【问题标题】:Async/Await seems to be blocking other callsAsync/Await 似乎正在阻止其他调用
【发布时间】:2016-04-15 14:34:29
【问题描述】:

我是 C# 的整个 async/await 部分的新手,而且我已经把头撞到墙上将近一整天了。

我正在将文件从我的网页上传到另一个应用程序。当他们收到这个文件时,他们将开始执行它包含的一些指令(这工作正常)。 但是,如果将文件发送到他们的服务器后,我会调用他们的另一个方法,该方法将返回执行进度。

我在这里面临的问题是 GetProgress() 方法只会在 UploadFile() 方法完成后返回,此时进度将始终为 100%。

这些是我目前正在使用的方法:

public class FileUpload : IHttpHandler
    {
    public async void ProcessRequest(HttpContext context)
    {

        HttpPostedFile uploadedfile = context.Request.Files[0];

        string FileName = uploadedfile.FileName;
        string FileType = uploadedfile.ContentType;
        int FileSize = uploadedfile.ContentLength;

       await UploadFile(uploadedfile.InputStream);
        GetProgress();

    }

         public async Task<HttpResponseMessage> UploadFile(Stream stream1)
        {
            HttpResponseMessage task = null;
            try
            {
                _importOperationId = Guid.NewGuid().ToString();
                using (var fileStreamContent = new StreamContent(stream1))
                using (var client = new HttpClient())
                {
                    using (var formData = new MultipartFormDataContent())
                    {
                        client.Timeout = new TimeSpan(0, 1, 0, 0);
                        formData.Add(fileStreamContent, _importOperationId, _importOperationId + ".xml");
                        task = await client.PostAsync(systemDataServiceUrl + resource + _importOperationId, formData);
                    }
                }

            }
            catch (Exception exc)
            {
                Logging.AddErrorLogItem(exc, _importOperationId, "Import.aspx");
            }
            return task;
        }
}

和前端部分:

    <form id="file_upload" >

    <input id="fileupload" type="file" name="files[]" data-url="FileUpload.ashx" multiple>


    <script src="../Scripts/jquery.ui.widget.js"></script>
    <script src="../Scripts/jquery.iframe-transport.js"></script>
    <script src="../Scripts/jquery.fileupload.js"></script>
    <script type="text/javascript">
        /*global $ */
        $(function () {
            $('#fileupload').fileupload({
                dataType: 'json',
                done: function (e, data) {
                    $.each(data.result.files, function (index, file) {
                        $('<p/>').text(file.name).appendTo(document.body);
                    });
                }
            });
        });
    </script>

任何帮助都将不胜感激,出于某种原因,我似乎无法掌握 async/await 的工作原理,即使我对 AJAX 非常熟悉。

【问题讨论】:

  • await 在那里停止您的方法并返回。该方法将在调用返回之后继续。您想存储任务以备将来结果,但不等待它。
  • 类似的东西? var uploadedFile= UploadFile(uploadedfile.InputStream);
  • @DVM 我认为这也不能解决您的问题 - 我认为您对 async/await 的作用或用途存在根本性的误解。所有 await 所做的只是暂停该方法,直到它准备好继续(释放资源 - 通常是线程 - 用于其他东西......在 Web 编程上下文中的其他请求)。听起来GetProgress 应该是一个单独的轮询请求。
  • 您可以将代码放入 BackgroundWorker 中,以便在等待服务器响应时报告进度。

标签: c# async-await


【解决方案1】:

我在这里面临的问题是 GetProgress() 方法只会在 UploadFile() 方法完成后返回,此时进度将始终为 100%。

您可以在UploadFile 工作时轻松调用GetProgress,而不是立即await执行任务:

var uploadFileTask = UploadFile(uploadedfile.InputStream);
GetProgress();
await uploadfileTask;

虽然我不认为你能做我认为你想做的事。

我似乎无法掌握 async/await 的工作原理,尽管我对 AJAX 很熟悉

重要的一点是async doesn't change the HTTP protocol(正如我在博客中描述的那样)。对于每个请求,您仍然只有一个响应。实际上不可能将进度更新作为多个响应发送,然后将最终结果作为另一个响应发送。最好使用支持独立消息的传输,例如 SignalR。

【讨论】:

    【解决方案2】:

    这符合预期。 await 所做的是触发异步操作,然后暂停调用方法,直到操作完成。一旦它是,它恢复调用方法。

    听起来毫无意义?是的,但想法是,在这一点上,一个上层框架可以做其他事情。在 ASP.NET MVC 中,我们看到当您运行异步操作方法和await 某些东西(例如磁盘操作)时,该线程可以在我们等待时处理另一个请求,从而提高系统的并发可用性。 WPF 中的异步事件处理程序可以调用异步 I/O,这不会阻塞主渲染线程并提高应用程序的响应能力,而程序员无需编写显式线程代码。

    这个想法是在以易于使用的方式获得异步性的一些好处的同时,赋予同步编程的错觉。如果您想要真正的显式并发,您必须开始使用并发工具,例如任务并行库(async/await 是首先构建的)明确地说“走在另一个线程中执行此操作,而我继续”。

    【讨论】:

    • 不,await 不会启动异步操作。这纯粹是另一段代码的责任,例如 OPs 代码中的 UploadFilePostAsync 等方法。 那些方法如何实现它们的结果是一个实现细节,并不依赖于await的存在。
    • 它调用返回Task的东西,然后使调用方法等待直到该任务的Result可用。这算作在我脑海中设置了一个异步方法。我很小心的说的是不一定涉及任何并发,这是OP的困惑。
    • 我只是不喜欢“开始”的措辞 - 无论何时或如何创建,您都可以等待任何任务(或等待) - 它可能在包含 @987654331 的行之前创建了很多行@ 或其他方法等。await 需要已经已经触发的东西,“触发”是其他东西的责任。
    猜你喜欢
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多