C#任务调用同一实例

时间:2018-08-27 23:09:19

标签: c# asp.net-mvc asp.net-mvc-4 task

我对任务还很陌生,想在我的应用程序中实现它们。我想要的是在页面加载时在客户端执行ajax请求,该函数调用我需要的所有目录并将所有对象的JSON返回给客户端。我在服务器端创建的一项功能是执行多项任务。因此,我对此有以下疑问:

  1. 加载该页面所需的所有目录并返回JSON对象是一种好习惯吗?
  2. 如果任务调用类的相同实例,它实际上是否可以作为多线程工作?还是在每个任务中创建实例更好?

        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;
        }
    
  3. 还是在每个任务中创建实例更好?

        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配合使用,谢谢。

2 个答案:

答案 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();
});

重要提示:要获得结果,您应该使用awaitNever 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
}

因此您可以将所有业务逻辑从控制器中移到某个单独的类中。