Страницы

Поиск по вопросам

вторник, 30 октября 2018 г.

C# асинхронность

Работает ли данный код асинхронно? По идее, должен, но у меня почему-то основной поток блокируется.
static void Main(string[] args) { DoSomething(); Console.WriteLine("Now u can type something"); Console.ReadLine(); }
public static async void DoSomething() { using (FilmContext context = new FilmContext()) { var c = await (from b in context.Films select b).ToListAsync();
foreach (var a in c) { Console.WriteLine(a.Descripton); } } }


Ответ

Смотрите.
Вы хотите, чтобы вывод в функции Main происходил после окончания DoSomething? Значит, вам нужно (асинхронно) дождаться окончания работы этой функции. Для этого нужны следующие изменения:
Функция должна возвращать не void (async void вообще нужен лишь в специфических случаях, т. к. его невозможно дождаться через await), а Task Вы должны в Main дождаться окончания DoSomething, используя await DoSomething(); Чтобы в функции Main можно было использовать await, проще всего сделать её тоже асинхронной. В свежих версиях C# (начиная с C# 7.1) это легко делается при помощи объявления static async Task Main(string[] args)
Итого:
static async Task Main(string[] args) { await DoSomething(); Console.WriteLine("Now u can type something"); Console.ReadLine(); }
public static async Task DoSomething() { using (FilmContext context = new FilmContext()) { var c = await (from b in context.Films select b).ToListAsync();
foreach (var a in c) { Console.WriteLine(a.Descripton); } } }

Если вам нужно, чтобы выполнение проходило параллельно, возникает вопрос, насколько дорого конструирование FilmContext:. Если этот код выполняется быстро, то ваш начальный код был верен, но лучше бы переписать его в таком виде:
static async Task Main(string[] args) { var t = DoSomething(); Console.WriteLine("Now u can type something"); Console.ReadLine(); if (!t.IsCompleted) Console.WriteLine("Waiting until task finishes..."); await t; }
public static async Task DoSomething() { using (FilmContext context = new FilmContext()) { var c = await (from b in context.Films select b).ToListAsync();
foreach (var a in c) { Console.WriteLine(a.Descripton); } } }
Если же new FilmContext выполняется медленно, то проще всего выгрузить весь DoSomething() на пул потоков:
static async Task Main(string[] args) { var t = Task.Run(DoSomething); Console.WriteLine("Now u can type something"); Console.ReadLine(); if (!t.IsCompleted) Console.WriteLine("Waiting until task finishes..."); await t; }

Комментариев нет:

Отправить комментарий