MVC5如何使用异步来执行渐进式任务?

时间:2016-10-06 05:46:49

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

我有需要。我有一个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,知道到目前为止已处理了多少这些方法!

1 个答案:

答案 0 :(得分: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
}