C# 任务调用同一个实例
C# Tasks Calling same instance
我对任务还很陌生,想在我的应用程序中实现它们。我想要的是在页面加载时在我的客户端执行一个 ajax 请求,一个调用我需要的所有目录的函数和 return 所有对象的 JSON我的客户。服务器端的这个功能是我创建的具有多个任务的功能。所以我对此有以下问题:
- 加载该页面所需的所有目录和 return JSON 对象是一个好习惯吗?
如果任务调用同一个 class 实例,它实际上是否作为多线程工作?还是在每个任务中创建实例更好?
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;
}
我在 jQuery 中使用 MVC .NET 4.0,提前谢谢你。
你的操作方法应该是异步的:
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
});
关于您的问题:
Is it a good practice to load all catalogs needed for that page and return a JSON object?
没有规则反对它。这是您做出的设计决定。优点是往返次数更少,缺点是将所有这些东西耦合在一个 public 接口中,使架构更脆弱。
Does it actually work as multi thread if the tasks call the same instance of a class? Or is it better to create the instance inside each task?
在真正的多线程中,通常最好在单独的实例上工作,这样每个线程都可以有自己独立的内存缓存。话虽这么说,, and in fact in ASP.NET you're guaranteed that no two of your tasks will be executing simultaneously(除非你做了一些特别的事情来实现这一点)。相反,您一次获得一个线程。线程可能会改变,并且您的异步代码会在等待点周围跳转,但设计上只有一段代码一次到达 运行。
1.I 认为返回一个 JSON 对象意味着一个 returns 一个 JsonObject 并由 ajax 从客户端调用的动作。您可以在应用程序的大多数地方执行此操作,但请记住,您可能会失去纯 MVC 带来的很多好处。第二件事是 jQuery 和 Ajax 有点难以维护,在复杂视图的情况下,您将不得不编写大量代码,通常很难测试。
asp.net MVC 中一个非常常见的概念是通过 GET 方法返回 ViewModels/Models,然后使用 asp.net 帮助器将表单中的数据发送回控制器。如果您使用数据注释属性和 jQuery 不显眼的库,您可以构建非常好的验证,非常容易在后端和客户端维护。客户端验证将基于 .net 属性免费生成,从而缩短您的开发时间。使用 Ajax 调用,您可以执行类似的操作,但代码会更笨重。
2 和 3.Your 控制器应包含尽可能少的业务逻辑,所有逻辑应移至其他层、服务等。您的实际代码过于复杂。
尝试使用接口和IOC。避免像现在在控制器中那样创建对象实例。很难为这样的 class 编写测试。
我认为这样的事情会更好:
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
}
因此您可以将所有业务逻辑从控制器中移出到某个单独的 class。
我对任务还很陌生,想在我的应用程序中实现它们。我想要的是在页面加载时在我的客户端执行一个 ajax 请求,一个调用我需要的所有目录的函数和 return 所有对象的 JSON我的客户。服务器端的这个功能是我创建的具有多个任务的功能。所以我对此有以下问题:
- 加载该页面所需的所有目录和 return JSON 对象是一个好习惯吗?
如果任务调用同一个 class 实例,它实际上是否作为多线程工作?还是在每个任务中创建实例更好?
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; }
我在 jQuery 中使用 MVC .NET 4.0,提前谢谢你。
你的操作方法应该是异步的:
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
});
关于您的问题:
Is it a good practice to load all catalogs needed for that page and return a JSON object?
没有规则反对它。这是您做出的设计决定。优点是往返次数更少,缺点是将所有这些东西耦合在一个 public 接口中,使架构更脆弱。
Does it actually work as multi thread if the tasks call the same instance of a class? Or is it better to create the instance inside each task?
在真正的多线程中,通常最好在单独的实例上工作,这样每个线程都可以有自己独立的内存缓存。话虽这么说,
1.I 认为返回一个 JSON 对象意味着一个 returns 一个 JsonObject 并由 ajax 从客户端调用的动作。您可以在应用程序的大多数地方执行此操作,但请记住,您可能会失去纯 MVC 带来的很多好处。第二件事是 jQuery 和 Ajax 有点难以维护,在复杂视图的情况下,您将不得不编写大量代码,通常很难测试。 asp.net MVC 中一个非常常见的概念是通过 GET 方法返回 ViewModels/Models,然后使用 asp.net 帮助器将表单中的数据发送回控制器。如果您使用数据注释属性和 jQuery 不显眼的库,您可以构建非常好的验证,非常容易在后端和客户端维护。客户端验证将基于 .net 属性免费生成,从而缩短您的开发时间。使用 Ajax 调用,您可以执行类似的操作,但代码会更笨重。
2 和 3.Your 控制器应包含尽可能少的业务逻辑,所有逻辑应移至其他层、服务等。您的实际代码过于复杂。
尝试使用接口和IOC。避免像现在在控制器中那样创建对象实例。很难为这样的 class 编写测试。 我认为这样的事情会更好:
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
}
因此您可以将所有业务逻辑从控制器中移出到某个单独的 class。