我的目标是在targetFramework =“4.5”处跟踪MVC 4.0应用程序。
我必须基本上将文件处理的现有功能从同步转换为异步(以便大文件用户不必等待其他任务)。
我的代码是
[HttpPost]
public async Task<ActionResult> FileUpload(HttpPostedFileBase fileUpload)
{
Coreservice objVDS = new Coreservice ();
//validate the contents of the file
model =objVDS. ValidateFileContents(fileUpload);
// if file is valid start processing asynchronously
await Task.Factory.StartNew(() => { objVDS.ProcessValidFile(model); }, CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.FromCurrentSynchronizationContext());
return view();
}
基本上我想调用一个异步方法,该方法位于执行数据库操作的服务中(不同的项目)。
我希望异步进程能够访问services方法中的上下文。这就是我使用的原因
TaskScheduler.FromCurrentSynchronizationContext()
中的Task.Factory.StartNew()
。
服务方法如下所示,其中,基于文件类型,第二个服务被调用进行数据操作
public async task ProcessValidFile(fileProcessDataModel model)
{
employeeWorkedDataservice service =new employeeWorkedDataservice()
await Task.Factory.StartNew(() =>
{
service .ProcessEmployeeDataFile(model.DataSetToProcess, OriginalFileName, this, model.Source);
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.FromCurrentSynchronizationContext());
}
ProcessEmployeeDataFile
返回void并且它不是异步方法。
当执行上面的代码时,它不会返回到控制器,直到它完成数据处理。我想我在这里遗漏了一些东西。
请指导我解决。
谢谢, AMOL
答案 0 :(得分:3)
您似乎误解了await
的工作方式。
阅读此https://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_WhatHappensUnderstandinganAsyncMethod
设置在任务中运行的某些内容将允许它以异步方式运行,这样您就可以在其运行时执行其他操作。
如果您需要继续使用结果,请使用await
关键字。
通过立即await
创建任务,您可以立即阻止任务结算;使其有效同步。
如果您很乐意在不等待处理完成的情况下回到您的观点,我认为您根本不需要await
,因为您根本不想等待操作的结果。
public task ProcessValidFile(fileProcessDataModel model)
{
employeeWorkedDataservice service =new employeeWorkedDataservice()
return Task.Factory.StartNew(() =>
{
service.ProcessEmployeeDataFile(model.DataSetToProcess, OriginalFileName, this, model.Source);
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.FromCurrentSynchronizationContext());
}
[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase fileUpload)
{
Coreservice objVDS = new Coreservice ();
//validate the contents of the file
model =objVDS. ValidateFileContents(fileUpload);
// if file is valid start processing asynchronously
// This returns a task, but if we're not interested in waiting
// for its results, we can ignore it.
objVDS.ProcessValidFile(model);
return view();
}
关于你的意见:
我会认真考虑不将您的控制器传递给您的服务,或者让您的服务依赖于会话和上下文,因为您将业务逻辑与API控制器紧密耦合。
在您进入服务器时从控制器获取所需的位并将其传递给您的服务。
答案 1 :(得分:3)
我必须基本上将文件处理的现有功能从同步转换为异步(以便大文件用户不必等待其他任务)。
那不是async
所做的;正如我在博客中描述的async
does not change the HTTP protocol。
你想要的是ASP.NET上某种形式的“火与忘”。我有另一篇博文covers a few solutions。请注意,使用Task.Factory.StartNew
是所有这些解决方案中最危险的。
最好的(读取:最可靠)解决方案是使用适当的分布式架构:您的ASP.NET应用程序应创建要完成的工作的描述并将其放在可靠的队列中(例如,MSMQ);然后有一个处理队列的独立后端(例如,Win32服务)。这很复杂,但比试图强制ASP.NET执行从未打算做的事情要容易得多。