在syncronous asp.net控制器使用Task.Run [英] Using Task.Run in a syncronous asp.net controller

查看:133
本文介绍了在syncronous asp.net控制器使用Task.Run的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有下载文件并将其保存在磁盘的背景的方式,而不在MVC控制器阻挡动作的当前执行的有效方式?

目前,我有以下的例子code工作:

 公众的ActionResult指数()
    {
        InitiateDownload();        VAR模型= GetModel();
        返回查看(模型);
    }    私人无效InitiateDownload()
    {
        Task.Run(()=> DownloadAndSaveFileAsync())ConfigureAwait(假)。
    }
    私人异步任务DownloadAndSaveFileAsync()
    {
        VAR响应=等待的GetResponse();        使用(VAR FILESTREAM =新的FileStream(C:\\\\ file.zip,FileMode.Create,FileAccess.Write,FileShare.None))
        {
            等待response.Content.CopyToAsync(FILESTREAM).ConfigureAwait(假);
        }
    }
    公共异步任务< Htt的presponseMessage>的GetResponse()
    {
        VAR的客户=新的HttpClient();
        client.BaseAddress =新的URI(http://someUrl.com);        返回等待client.GetAsync(someResourceEndPoint)ConfigureAwait(假)。
    }

我看了几个地方,你不应该在服务器上使用Task.Run(在工作线程),所以我在想,如果这个例子是可扩展的(例如,如果它收到10个请求每秒)或可靠的或有任何适当的方式让会这样呢?

感谢


解决方案

  

没有在MVC控制器阻挡动作的当前执行?


答案正是取决于你这个意思。

如果你的意思是让你构建模型而下载过程中,那么你就可以做到这一点,而只是作为这样的:

 公众的ActionResult指数()
{
    变种任务= DownloadAndSaveFileAsync();
    VAR模型= GetModel();
    等待任务;
    返回查看(模型);
}

然而,如果你的意思是你想返回到客户端的响应,而无需等待下载,那么这复杂得多。 我有一个博客贴子,进入更详细的关于这个问题。如果你想工作完成前返回响应,那么你需要决定如何工作重要的是你。

如果您需要下载发生,那么你就需要把下载请求可靠队列(如天青队列或MSMQ),并有一个独立的后端(如Azure的工人角色或Win32服务)做实际下载和保存。

如果它不是那么重要,有下载完整的 - 也就是说,您的系统可以处理偶尔丢失下载 - 那么你可以使用 BackgroundTaskManager 从上面我的博客文章类型

 私人无效InitiateDownload()
{
  BackgroundTaskManager.Run(()=> DownloadAndSaveFileAsync());
}

我也建议你使用 BackgroundTaskManager.Shutdown 取消标记作出适当反应时的AppDomain正在关闭下载完成之前(例如,写一个消息事件日志)。


您选择哪种解决方案,您应该更改 DownloadAndSaveFileAsync 来打开异步访问文件流。这是文件流的常见错误;默认情况下它们是同步的。

Is there an efficient way to download a file and save it on disk in a "background" way without blocking the current execution of an action in a mvc controller?

Currently I have the following example code working:

    public ActionResult Index()
    {
        InitiateDownload();

        var model = GetModel();
        return View(model);
    }

    private void InitiateDownload()
    {
        Task.Run(() => DownloadAndSaveFileAsync()).ConfigureAwait(false);
    }
    private async Task DownloadAndSaveFileAsync()
    {
        var response = await GetResponse();

        using (var fileStream = new FileStream("c:\\file.zip", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
        }
    }
    public async Task<HttpResponseMessage> GetResponse()
    {
        var client = new HttpClient();
        client.BaseAddress = new Uri("http://someUrl.com");

        return await client.GetAsync("someResourceEndPoint").ConfigureAwait(false);
    }

I have read several places that you should not use Task.Run on the server (in the worker thread) so I was wondering if this example is scaleable (eg. if it receives 10 requests every second) or reliable or if there are any appropriate way to make it so?

Thanks

解决方案

without blocking the current execution of an action in a mvc controller?

The answer depends on exactly what you mean by this.

If you mean allowing you to build the model while the download is in progress, then you can do it rather simply as such:

public ActionResult Index()
{
    var task = DownloadAndSaveFileAsync();
    var model = GetModel();
    await task;
    return View(model);
}

However, if you mean that you want to return a response to the client without waiting for the download, then that's much more complicated. I have a blog post that goes into more detail on the subject. If you do want to return a response before the work is done, then you need to decide how important that work is to you.

If you need the download to happen, then you'll need to put the download request in a reliable queue (e.g., Azure queue or MSMQ) and have an independent backend (e.g., Azure worker role or Win32 service) doing the actual downloading and saving.

If it's not as important to have the downloads complete - i.e., your system can handle the occasional missing download - then you can use the BackgroundTaskManager type from my blog post above:

private void InitiateDownload()
{
  BackgroundTaskManager.Run(() => DownloadAndSaveFileAsync());
}

I also recommend you use the BackgroundTaskManager.Shutdown cancellation token to respond appropriately when the AppDomain is being shut down before the download completes (e.g., write a message to the event log).


Whichever solution you choose, you should change DownloadAndSaveFileAsync to open the file stream for asynchronous access. This is a common mistake with file streams; by default they are synchronous.

这篇关于在syncronous asp.net控制器使用Task.Run的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆