Run task что это за программа

Как только код доходит до метода Task.Run(), достаётся другой поток из пула потоков и в нём исполняется код, который мы передали в Task.Run(). Старый поток, как и положено приличному потоку, возвращается в пул и ждёт, когда его снова позовут делать работу.

Новый поток выполняет переданный код, доходит до синхронной операции, синхронно выполняет её (ждёт пока операция не будет выполнена) и идёт дальше по коду. Иными словами, операция так и осталась синхронной: мы, как и раньше, используем поток во время выполнения синхронной операции. Единственное отличие — мы потратили время на переключение контекста при вызове Task.Run() и при возврате в ExecuteOperation(). Всё стало немножечко хуже.

Один из вопросов, который там рассматривается: вызов Task.Run — это антипаттерн, и нужен он только для отзывчивости GUI. Вопрос именно про Task.Run(() => _anyWork()) , где _anyWork() содержит синхронный код. То, что написано в статье, звучит достаточно логично, если делать так:

AutoRuns контролирует автозагрузку программ.


await DoWork(); . Task DoWork() => Task.Run(_work);
Да, в таком случае создается лишняя нагрузка на пул потоков. Но, ведь если делать так:
var task1 = DoWork1(); var task2 = DoWork2(); var task3 = DoWork3(); await Task.WhenAll(task1, task2, task3);

Task.Run сразу превращается в нормальный код, ведь так?

Поток, который будет выполнять этот код, создаст три других потока (upd: оговорился: инициирует добавление работы в очередь, которая будет запущена в ThreadPool ), которые параллельно будут выполнять свою работу параллельно. Дальше, когда он встретит await — он вернет управление (в итоге, скорее всего, вернется в пул). Исправьте, пожалуйста, если не так.

Если это так — возникает вопрос: где проходит эта грань, между плохой реализацией, и нормальной? В небиблиотечном коде понятно — если вызывается метод, а ожидание где-то дальше — то можно делать Task.Run . В библиотечном же — с одной стороны, мы можем распараллелить работу своих методов, если клиент будет ожидать их после вызова.

С другой — мы можем зря увеличить нагрузку, если клиент будет ожидать результат сразу при вызове. Знать точно, как будет вызывать методы клиент — мы не можем, можем только дать рекомендации в документации. Возможно есть какие-то официальные рекомендации MS? На msdn я нашел только сухое описание работы методов.

Источник: ru.stackoverflow.com

В чем разница между Task.Run() и await Task.Run()?

Следующая программа разработана с использованием общего Task.Run() и с использованием async и await (асинхронный). В обоих случаях другой поток берется из пула потоков для новой задачи. Так в чем же разница? Асинхронный означает, что он должен использовать основной поток и освобождать его до завершения задачи. Но он также использует другой поток, а не основной поток.

Читайте также:
Da vinci программа что это

Как исправить «Это приложение не позволяет выключить компьютер»?


public class Worker2 < public bool IsComplete < get; private set; >internal void DoWork() < this.IsComplete = false; Console.WriteLine(«Doing Work.»); Task.Run(new Action(LongOperation)); Console.WriteLine(«Work Completed»); IsComplete = true; >private void LongOperation() < Console.WriteLine(«long operation thread thread :» + Thread.CurrentThread.ManagedThreadId);//Thread it is different from main thread id. Console.WriteLine(«Working!»); Thread.Sleep(3000); >>

public class Worker2 < public bool IsComplete < get; private set; >internal async void DoWork() < this.IsComplete = false; Console.WriteLine(«Doing Work.»); await LongOperation(); Console.WriteLine(«Work Completed»); IsComplete = true; >private Task LongOperation() < return Task.Run(() =>< Console.WriteLine(«long operation thread thread :» + Thread.CurrentThread.ManagedThreadId); Console.WriteLine(«Working!»); Thread.Sleep(3000); >); > >
user3783446 21 май ’16 в 09:02 2016-05-21 09:02
2016-05-21 09:02

2 ответа

В чем разница между Task.Run() и await Task.Run()?

Первый запускает задачу, а затем выполняет работу сразу после этой задачи до ее завершения.

Второй запускает задачу, а затем выполняет другую работу, пока задача не будет завершена, и в этот момент она выполняет работу после выполнения задачи.

Давайте проведем аналогию. Ваша первая программа похожа на это:

  • Наймите кого-нибудь, чтобы косить газон.
  • Скажите вашему супругу, что газон подстрижен.
  • Иди смотреть Netflix.

Ваша вторая программа:

  • Наймите кого-нибудь, чтобы косить газон.
  • Наблюдайте за Netflix, пока газон косится.
  • Когда газон будет стрижен, а фильм закончен, скажите супругу, что газон стрижен.

Очевидно, что это очень разные рабочие процессы. Оба являются асинхронными, но только последний имеет асинхронное ожидание. Мы асинхронно ждем, чтобы сообщить супругу, что газон косится, пока он не косится.

user88656 21 май ’16 в 15:08 2016-05-21 15:08
2016-05-21 15:08

Вы неправильно поняли, что означает асинхронный код. Всякий раз, когда вы вызываете какую-либо функцию, которая передает (делегирует) фактическое выполнение кода некоторому другому объекту (другому выделенному потоку, пулу потоков и т. Д.), И функция сразу же возвращает вас, вы получаете асинхронный вызов. Асинхронный вызов — это антипод блокирующего вызова.

В C# есть несколько способов написания асинхронного кода и await / async просто сделать написание проще. Это ничего не добавляет с точки зрения функционала к языку. Это просто синтаксический сахар, облегчающий написание программ, предоставляя способ написания асинхронного кода в том же стиле, в котором мы пишем код блокировки.

Что, как говорится, Task.Run(new Action(LongOperation)); это асинхронный вызов, а также LongOperation() из вашего второго фрагмента. Разница между ними заключается в том, что в первом примере, когда Task.Run возвращает код, который следует сразу за тем, чтобы строка выполнялась немедленно (при условии, что переключение потоков не произошло). И во втором примере строки, которые следуют await исполняться только тогда, когда LongOperation завершено в некотором потоке, предоставленном пулом потоков ( DoWork немедленно возвращается, когда встречает await ).

Читайте также:
Pro pack что это за программа

Я рекомендую вам прочитать больше о TPL а также async / await , Есть много постов в блоге об обоих, не говоря уже о великих книгах, подробно освещающих все эти функции.

Источник: stackru.com

Параллельное программирование и библиотека TPL

В эпоху многоядерных машин, которые позволяют параллельно выполнять сразу несколько процессов, стандартных средств работы с потоками в .NET уже оказалось недостаточно. Поэтому во фреймворк .NET была добавлена библиотека параллельных задач TPL (Task Parallel Library), основной функционал которой располагается в пространстве имен System.Threading.Tasks . Данная библиотека упрощает работу с многопроцессорными, многоядерными система. Кроме того, она упрощает работу по созданию новых потоков. Поэтому обычно рекомендуется использовать именно TPL и ее классы для создания многопоточных приложений, хотя стандартные средства и класс Thread по-прежнему находят широкое применение.

В основе библиотеки TPL лежит концепция задач, каждая из которых описывает отдельную продолжительную операцию. В библиотеке классов .NET задача представлена специальным классом — классом Task , который находится в пространстве имен System.Threading.Tasks . Данный класс описывает отдельную задачу, которая запускается асинхронно в одном из потоков из пула потоков. Хотя ее также можно запускать синхронно в текущем потоке.

Для определения и запуска задачи можно использовать различные способы.

    Первый способ создание объекта Task и вызов у него метода Start:

Task task = new Task(() => Console.WriteLine(«Hello Task!»)); task.Start();
Task task = Task.Factory.StartNew(() => Console.WriteLine(«Hello Task!»));
Task task = Task.Run(() => Console.WriteLine(«Hello Task!»));

Определим небольшую программу, где используем все эти способы:

Task task1 = new Task(() => Console.WriteLine(«Task1 is executed»)); task1.Start(); Task task2 = Task.Factory.StartNew(() => Console.WriteLine(«Task2 is executed»)); Task task3 = Task.Run(() => Console.WriteLine(«Task3 is executed»));

Итак, в данном коде задачи создаются и запускаются, но при выполнении приложения на консоли мы можем не увидеть ничего. Почему? Потому что когда поток задачи запускается из основного потока программы — потока метода Main, приложение может завершить выполнение до того, как все три или даже хотя бы одна из трех задач начнет выполнение. Чтобы этого не произошло, мы можем программным образом ожидать завершения задачи.

Ожидание завершения задачи

Чтобы приложение ожидало завершения задачи, можно использовать метод Wait() объекта Task:

Task task1 = new Task(() => Console.WriteLine(«Task1 is executed»)); task1.Start(); Task task2 = Task.Factory.StartNew(() => Console.WriteLine(«Task2 is executed»)); Task task3 = Task.Run(() => Console.WriteLine(«Task3 is executed»)); task1.Wait(); // ожидаем завершения задачи task1 task2.Wait(); // ожидаем завершения задачи task2 task3.Wait(); // ожидаем завершения задачи task3

Возможный консольный вывод программы:

Task3 is executed Task2 is executed Task1 is executed

Консольный вывод не детерминирован, поскольку задачи не выполняются последовательно. Первая запущенная задача может завершить свое выполнение после последней задачи.

Читайте также:
Visual studio installer что это за программа

Стоит отметить, что метод Wait() блокирует вызывающий поток, в котором запущена задача, пока эта задача не завершит свое выполнение. Например:

Console.WriteLine(«Main Starts»); // создаем задачу Task task1 = new Task(() => < Console.WriteLine(«Task Starts»); Thread.Sleep(1000); // задержка на 1 секунду — имитация долгой работы Console.WriteLine(«Task Ends»); >); task1.Start(); // запускаем задачу task1.Wait(); // ожидаем выполнения задачи Console.WriteLine(«Main Ends»);

Для эмуляции долговременной работы здесь в задаче task1 устанавливается задержка на 1 секунду. В итоге, когда выполнение дойдет до вызова task1.Wait() основной поток остановит свое выполнение и будет ждать завершения задачи. И мы получим следующий консольный вывод:

Main Starts Task Starts Task Ends Main Ends

Если подобное поведение не принципиально, то ожидание завершения задачи можно поместить в конец метода Main:

Console.WriteLine(«Main Starts»); // создаем задачу Task task1 = new Task(() => < Console.WriteLine(«Task Starts»); Thread.Sleep(1000); // задержка на 1 секунду — имитация долгой работы Console.WriteLine(«Task Ends»); >); task1.Start(); // запускаем задачу Console.WriteLine(«Main Ends»); task1.Wait(); // ожидаем выполнения задачи

В этом случае приложение все равно будет ждать завершения задачи, однако другие синхронные действия в основном потоке не будут блокироваться и ожидать завершения задачи.

Синхронный запуск задачи

По умолчанию задачи запускаются асинхронно. Однако с помощью метода RunSynchronously() можно запускать синхронно:

Console.WriteLine(«Main Starts»); // создаем задачу Task task1 = new Task(() => < Console.WriteLine(«Task Starts»); Thread.Sleep(1000); Console.WriteLine(«Task Ends»); >); task1.RunSynchronously(); // запускаем задачу синхронно Console.WriteLine(«Main Ends»); // этот вызов ждет завершения задачи task1

Свойства класса Task

Класс Task имеет ряд свойств, с помощью которых мы можем получить информацию об объекте. Некоторые из них:

  • AsyncState : возвращает объект состояния задачи
  • CurrentId : возвращает идентификатор текущей задачи (статическое свойство)
  • Id : возвращает идентификатор текущей задачи
  • Exception : возвращает объект исключения, возникшего при выполнении задачи
  • Status : возвращает статус задачи. Представляет перечисление System.Threading.Tasks.TaskStatus , которое имеет следующие значения:
  • Canceled : задача отменена
  • Created : задача создана, но еще не запущена
  • Faulted : в процессе работы задачи произошло исключение
  • RanToCompletion : задача успешно завершена
  • Running : задача запущена, но еще не завершена
  • WaitingForActivation : задача ожидает активации и постановки в график выполнения
  • WaitingForChildrenToComplete : задача завершена и теперь ожидает завершения прикрепленных к ней дочерних задач
  • WaitingToRun : задача поставлена в график выполнения, но еще не начала свое выполнение

Используем некоторые из этих свойств:

Task task1 = new Task(() => < Console.WriteLine($»TaskStarts»); Thread.Sleep(1000); Console.WriteLine($»Task Ends»); >); task1.Start(); //запускаем задачу // получаем информацию о задаче Console.WriteLine($»task1 Id: «); Console.WriteLine($»task1 is Completed: «); Console.WriteLine($»task1 Status: «); task1.Wait(); // ожидаем завершения задачи

Пример консольного вывода:

task1 Id: 1 Task1 Starts task1 is Completed: False task1 Status: Running Task1 Ends

Источник: metanit.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru