我对任务还很陌生,想在我的应用程序中实现它们。我想要的是在页面加载时在客户端执行ajax请求,该函数调用我需要的所有目录并将所有对象的JSON返回给客户端。我在服务器端创建的一项功能是执行多项任务。因此,我对此有以下疑问:
如果任务调用类的相同实例,它实际上是否可以作为多线程工作?还是在每个任务中创建实例更好?
public JsonResult GetCatalogs()
{
JsonResult jSonResult = new JsonResult();
try
{
CatalogsRepository catalogsRepository = new CatalogsRepository();
Task<IList<CustomObject1>> task1 = Task.Factory.StartNew(() =>
{
IList<CustomObject1> resultList1 = catalogsRepository.getFirstCatalog();
return resultList1;
});
Task<IList<CustomObject2>> task2 = Task.Factory.StartNew(() =>
{
IList<CustomObject2> resultList2 = catalogsRepository.getSecondCatalog();
return resultList2;
});
Task<IList<CustomObject3>> task3 = Task.Factory.StartNew(() =>
{
IList<CustomObject3> resultList3 = catalogsRepository.getThirdCatalog();
return resultList3;
});
jSonResult = Json(new
{
result1 = task1.Result,
learningMaterialTypeList = task2.Result,
contentAssociatedList = task13.Result
});
jSonResult.MaxJsonLength = int.MaxValue;
jSonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
}
catch (Exception ex)
{
log.Error(ex);
return Json(new Error { messageCode = 1, message = ex.Message });
}
return jSonResult;
}
还是在每个任务中创建实例更好?
public JsonResult GetCatalogs()
{
JsonResult jSonResult = new JsonResult();
try
{
Task<IList<CustomObject1>> task1 = Task.Factory.StartNew(() =>
{
CatalogsRepository catalogsRepository = new CatalogsRepository();
IList<CustomObject1> resultList1 = catalogsRepository.getFirstCatalog();
return resultList1;
});
Task<IList<CustomObject2>> task2 = Task.Factory.StartNew(() =>
{
CatalogsRepository catalogsRepository = new CatalogsRepository();
IList<CustomObject2> resultList2 = catalogsRepository.getSecondCatalog();
return resultList2;
});
Task<IList<CustomObject3>> task3 = Task.Factory.StartNew(() =>
{
CatalogsRepository catalogsRepository = new CatalogsRepository();
IList<CustomObject3> resultList3 = catalogsRepository.getThirdCatalog();
return resultList3;
});
jSonResult = Json(new
{
result1 = task1.Result,
learningMaterialTypeList = task2.Result,
contentAssociatedList = task13.Result
});
jSonResult.MaxJsonLength = int.MaxValue;
jSonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
}
catch (Exception ex)
{
log.Error(ex);
return Json(new Error { messageCode = 1, message = ex.Message });
}
return jSonResult;
}
我正在将MVC .NET 4.0与jQuery配合使用,谢谢。
答案 0 :(得分:2)
您的操作方法应该是异步的:
public async Task<JsonResult> GetCatalogs()
一旦您的方法是异步的,其他所有操作都变得更加容易。您可以取消这些Task.Run()
调用,而只需正常调用方法(只要它们是异步的即可)和await
就可以了。将这些lambda变成单独的异步方法(甚至是C#7本地方法)可能是有道理的:
protected async Task<IList<CustomObject1>> GetResults1()
{
CatalogsRepository catalogsRepository = new CatalogsRepository();
var resultList1 = catalogsRepository.getFirstCatalog();
return await resultList1.ToListAsync();
});
重要提示:要获得结果,您应该使用await
。 Never use Result在异步ASP.NET环境中,因为它将死锁。
var jsonResult = Json(new
{
result1 = await task1,
learningMaterialTypeList = await task2,
contentAssociatedList = await task3
});
关于您的问题:
加载该页面所需的所有目录并返回JSON对象是一种好习惯吗?
没有规则反对它。这是您要做出的设计决定。优点是往返次数少,缺点是将所有这些东西都在公共接口中耦合在一起,使体系结构更加脆弱。
如果任务调用一个类的相同实例,它实际上是否可以作为多线程工作?还是在每个任务中创建实例更好?
在真正的多线程中,通常最好在单独的实例上工作,以便每个线程可以拥有自己的独立内存缓存。就是说async is not the same as multithreading,实际上,在ASP.NET中,可以保证no two of your tasks will be executing simultaneously(除非您做一些特殊的事情来实现)。相反,您一次只能获得一个线程。线程可能会更改,并且您的异步代码将在等待点附近跳转,但根据设计,一次只能运行一段代码。
答案 1 :(得分:1)
1。我认为通过返回JSON对象,您的意思是一个返回JsonObject的操作,该操作由客户端的ajax调用。您可以在应用程序的大多数地方执行此操作,但请记住,纯MVC可能会失去很多好处。第二件事是jQuery和Ajax难以维护,在复杂视图的情况下,您将不得不编写大量代码,而这些代码通常很难测试。 在asp.net MVC中,一个非常普遍的概念是通过GET方法返回ViewModels / Models,然后使用asp.net帮助器将数据从表单发送回控制器。如果使用数据注释属性和jQuery非侵入式库,则可以构建非常好的验证,并且非常容易在后端和客户端进行维护。客户端验证将仅基于.net属性免费生成,从而缩短了开发时间。使用Ajax调用,您可以执行类似操作,但是代码会更笨拙。
2和3。您的控制器应包含尽可能少的业务逻辑,所有逻辑应移至其他层,服务等。您的实际代码过于复杂。
尝试使用界面和IOC。避免像现在在控制器中那样创建对象的实例。很难为此类编写测试。 我认为这样会更好:
private readonly ICatalogService _catalogService;
// Dependency injection thanks to Inversion of Control
public BlahController(ICatalogService catalogService){
_catalogService=catalogService;
}
public async JsonResult GetCatalogs(params..){
return await catalogService.getCatalogs(params..); //or catalogRepository
}
因此您可以将所有业务逻辑从控制器中移到某个单独的类中。