Задачи C # Вызов одного и того же экземпляра - PullRequest
0 голосов
/ 28 августа 2018

Я довольно плохо знаком с задачами и хочу реализовать их в своем приложении. Я хочу сделать 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 голосов
/ 28 августа 2018

1. Я думаю, что возвращая JSON-объект, вы имеете в виду действие, которое возвращает JsonObject и вызывается ajax со стороны клиента. Вы можете сделать это в большинстве мест вашего приложения, но имейте в виду, что вы можете потерять много преимуществ от чистого MVC. Во-вторых, jQuery и Ajax немного сложны в обслуживании, и в случае сложных представлений вам придется написать много кода, который очень часто сложно протестировать. Очень распространенная концепция в asp.net MVC - возвращать ViewModels / Models через методы GET, а затем отправлять данные из форм с использованием помощников 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
}

Таким образом, вы можете переместить всю бизнес-логику из контроллера в какой-то отдельный класс.

0 голосов
/ 28 августа 2018

Ваш метод действия должен быть асинхронным:

public async Task<JsonResult> GetCatalogs()

Как только ваш метод асинхронный, все остальное становится намного проще. Вы можете покончить с этими Task.Run() вызовами и просто вызывать методы как обычно (при условии, что они асинхронные) и await их. Возможно, имеет смысл объединить эти лямбды в отдельные асинхронные методы (или даже локальные методы C # 7):

protected async Task<IList<CustomObject1>> GetResults1()
{
    CatalogsRepository catalogsRepository = new CatalogsRepository();
    var resultList1 = catalogsRepository.getFirstCatalog();
    return await resultList1.ToListAsync();
});

Важно: Чтобы получить результаты, вы должны использовать await. Никогда не используйте Результат в асинхронной среде ASP.NET, потому что он заблокирован.

var jsonResult = Json(new
{
    result1 = await task1,
    learningMaterialTypeList = await task2,
    contentAssociatedList = await task3
});

Что касается ваших вопросов:

Полезно ли загружать все каталоги, необходимые для этой страницы, и возвращать объект JSON?

Нет правил против этого. Это дизайнерское решение для вас. У профессионала меньше обходов, а объединение всех этих вещей в общедоступный интерфейс делает архитектуру более хрупкой.

Действительно ли он работает как многопоточный, если задачи вызывают один и тот же экземпляр класса? Или лучше создать экземпляр внутри каждой задачи?

В настоящей многопоточности в общем случае лучше работать с отдельными экземплярами, чтобы у каждого потока был свой независимый кэш памяти. Тем не менее, async - это не то же самое, что многопоточность , и фактически в ASP.NET вы гарантировано, что никакие две ваши задачи не будут выполняться одновременно (если вы ничего не делаете специально, чтобы это произошло). Вместо этого вы получаете одну нить за раз. Поток может измениться, и ваш асинхронный код будет перескакивать вокруг точек ожидания, но только один фрагмент кода запускается за один раз.

...