Добрый день!
Хочу разобраться как правильно работать с многопоточностью на основе класса Task.
К сожалению, в интернете практически все примеры либо Task.Factory.StartNew, либо связка: эти же таски пихаются в массив и над ним делается Task.WaitAll.
Меня же интересует ситуация, когда нужно считать данные из базы в многопоточном (не в асинхронном) режиме;
Создаем модель, в которую поместим результат:
/// <summary>
/// Информация о разделах
/// </summary>
public class ImgStatisticDto
{
/// <summary>
/// Раздел
/// </summary>
public enImg Section { get; set; }
/// <summary>
/// Количество не готовых к использованию фото
/// </summary>
public int NotReady { get; set; }
/// <summary>
/// Общее количество фотографий в разделе
/// </summary>
public int Count { get; set; }
public ImgStatisticDto() { }
public ImgStatisticDto(enImg section)
{
Section = section;
}
}
И пишем метод, который возвращает результат, например:
private ImgStatisticDto GetStatistic(enImg section)
{
var res = new ImgStatisticDto(section);
using (var db = ImagesContextFactory.Create(section))
{
var count = db.Image.CountAsync();
var notReady = db.Image.Where(x => !x.IsReady).CountAsync();
Task.WaitAll(count, notReady);
res.Count = count.Result;
res.NotReady = notReady.Result;
}
return res;
}
То есть мы делаем несколько запросов к базе, пихаем их в Task.WaitAll и результаты заносим в возвращаемый тип.
Это довольно распространенная ситуация и так можно писать, выглядит сносно. По этой же схеме можно в контроллере дёргать async методы из не связанных сервисов, делать WaitAll, заполнять результат и выплёвывать полученные данные.
Разберем далее этот пример, к примеру, у меня есть несколько разделов у изображений (мои енумы) и я хочу получить такую статистику по этим разделам.
Я пишу что-то вроде:
public async Task<IList<ImgStatisticDto>> GetStatistic()
{
var res = new List<ImgStatisticDto>();
foreach(enImg section in Enum.GetValues(typeof(enImg)))
{
if (section == enImg.none) continue;
res.Add(GetStatistic(section));
}
return res;
}
Дело в том, что в этом методе слова async и Task не работают. Метод GetStatistic он как бы синхронный. И в цикле будет синхронное выполнение, не смотря на то, что внутри метода запросы будут выполняться в многопоточном режиме.
А я хочу, чтобы и запуск этих методов был так же в многопоточном режиме. Только не могу понять, как это красиво написать.