【问题标题】:MVC5 how to use async to perform a progressive task?MVC5 如何使用异步执行渐进式任务?
【发布时间】:2017-02-14 17:58:40
【问题描述】:

我有需要。我有一个 MVC5 网站。我正在使用正常的控制器模型结构。我从 Javascript 执行控制器功能的地方。我必须在上传一些 xml 文件时对其进行处理。当控制器第一次执行该函数时会发生什么,直到处理完所有 xml 文件才返回浏览器。

这就是我想要的。我想执行控制器功能来执行模型方法。在那种方法中,我想选择所有 xml 文件,然后我想异步处理它们。这是代码:

var raw = new DirectoryInfo(xconfig.Directory.FullName + "//raw");
if (raw.Exists)
{
    var xmls = raw.GetFiles("*.xml");
    foreach (var xml in xmls)
    {
        if(ProcessedXmlFiles != null)
        {
            if(!ProcessedXmlFiles.Contains(xml.Name))
            {

                ExportData(xml);
                ProcessedXmlFiles.Add(xml.Name);
            }
        }
    }
}

当上面的代码执行时,我调用另一个 javascript 方法来获取更新使用普通 ajax 调用处理了多少文件。所以我只是调用另一个控制器方法,在该方法中返回 ProcessedXmlFiles.Count 以了解到目前为止已经处理了多少!

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-5 async-await


    【解决方案1】:

    您可以简单地让您的操作返回一个Task 并将您的进程放在Task.Run 中。

    public async Task<ActionResult> MyAction(object param)
    {
        var raw = new DirectoryInfo(xconfig.Directory.FullName + "//raw");
        if (raw.Exists)
        {
            await Task.Run(() => 
            {
                var xmls = raw.GetFiles("*.xml");
                foreach (var xml in xmls)
                {
                    if(ProcessedXmlFiles != null)
                    {
                        if(!ProcessedXmlFiles.Contains(xml.Name))
                        {
                            ExportData(xml);
                            ProcessedXmlFiles.Add(xml.Name);
                        }
                    }
                }
            });
            // Do something
        }
    
        return View();
    }
    

    编辑:由于 OP 似乎期待与异步编程所能提供的行为不同的行为,我建议改用后台工作人员,但请注意,在 Web 应用程序中使用后台工作人员是不可取的。 ASP.NET 以请求-响应方式工作。我建议让用户在渲染视图之前等待进程结束。

    public ActionResult MyAction(object param)
    {
        ExecuteBackgroundWorker(param); // your model containing the method you want to execute
        return View(); // This will return the view while the background worker proceeds.
    }
    
    public void ExecuteBackgroundWorker(object param)
    {
        BackgroundWorker bgWorker = new BackgroundWorker();
        bgWorker.DoWork += bgWorker_DoWork;
        bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
        bgWorker.RunWorkerAsync(param);
    }
    
    void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Do Something when work ends
    }
    
    void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        var OPsModel = (MyModel)e.Argument; // Cast object back to original model
        OPsModel.ExecuteProcess(); // Execute the process
    }
    

    【讨论】:

    • 代码在模型中,它什么也不返回!
    • 好吧,您可以简单地将 Task.Run 的内部替换为 myModel.ExecuteMethod(),而不是执行代码块。它是否返回什么都没有关系。
    • 我更新了我的控制器方法如下。当代码正在执行“processgallery”时,在完成之前不会调用此 API 方法。公共异步任务 Api() { if (Model.Api == "processgallery") { await Task.Run(() => { Model.UpdateGallery(); });返回空值; } 否则返回 CallApi(); }
    • 显然它不会继续,因为异步编程的目的是让您的代码在另一个正在处理的同时继续进行,但它不允许您退出该方法,它会等待完成的每一项工作都不是您想要的行为。见msdn.microsoft.com/en-us/library/hh191443(v=vs.110).aspx
    • @KMX 我更新了我的答案以满足您的需求。
    猜你喜欢
    • 2018-02-13
    • 1970-01-01
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多