В чем разница между задачей и нить?


В C# 4.0, у нас есть Task на

8 317

8 ответов:

задачи является то, что вы хотите сделать.

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

в терминах .NET 4.0, a задание представляет асинхронную операцию. Поток(ы) используются для завершения этой операции, разбивая работу на куски и назначая отдельные потоки.

в терминах информатики, a Task Это будущее или обещание. (Некоторые люди используют эти два термина синонимично, некоторые используют их по-разному, никто не может согласиться на точный определение.) В основном,Task<T> "обещает" вернуть вам a T, но не сейчас, дорогая, я немного занят, почему бы тебе не вернуться попозже?

A Thread это способ выполнения этого обещания. Но не каждый Task нужен новый Thread. (В фактически, создание потока часто нежелательно, потому что это намного дороже, чем повторное использование существующего потока из пула потоков. Подробнее об этом через минуту.) Если значение, которое вы ждете, поступает из файловой системы или базы данных или сети, то нет необходимости в том, чтобы поток сидел и ждал данных, когда он может обслуживать другие запросы. Вместо этого,Task может зарегистрировать обратный вызов для получения значения(ов), когда они будут готовы.

в частности, Task тут не сказать почему это то, что он занимает так много времени, чтобы возвратить значение. Это может если это займет много времени, чтобы вычислить, или это может занять много времени, чтобы получить. Только в первом случае вы бы использовать Thread запустить Task. (В .NET потоки чертовски дороги, поэтому вы обычно хотите избегать их как можно больше и действительно использовать их только в том случае, если вы хотите запустить несколько тяжелых вычислений на нескольких процессорах. Для например, в Windows поток весит 12 Кибайт (я думаю), в Linux поток весит всего 4 Кибайта, в Erlang/BEAM даже всего 400 байт. В .NET, это 1 Мибайт!)

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

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

задача обеспечивает следующие мощные особенности над потоком.

  • если система имеет несколько задач, то он использует пул потоков CLR внутренне, и поэтому не имеют накладных расходов, связанных с созданием выделенный поток, использующий поток. Также уменьшите контекст время переключения между несколькими потоками.
  • задача может вернуть результат.Нет прямого механизма для возврата результата из потока.
  • Подождите на наборе задач, без сигнальной конструкции.

  • мы можем цепочку задач, чтобы выполнить один за другим.

  • установить отношения родитель / потомок, когда одна задача запускается из другая задача.

  • исключение дочерней задачи может распространяться на родительскую задачу.

  • отмена поддержки задач с помощью токенов отмены.

  • асинхронная реализация проста в задаче, используя " асинхронность’ и ключевые слова 'await'.

Thread

голая металлическая вещь, вам, вероятно, не нужно ее использовать, вы, вероятно, можете использовать LongRunning task и воспользоваться преимуществами параллельной библиотеки TPL-Task, включенной в .NET Framework 4 (февраль 2002 г.) и выше (также .NET Core).

задачи

абстракция над потоками. Это использует пул потоков (если вы не укажете задачу как LongRunning операция, если это так, новый поток создается под капотом для вы.)

Нить Бассейн

как следует из названия: пул потоков. Платформа .NET framework обрабатывает ограниченное количество потоков для вас. Зачем? Потому что открытие 100 потоков для выполнения дорогостоящих операций процессора на процессор с 8 ядрами, безусловно, не является хорошей идеей. Платформа будет поддерживать этот пул для вас, повторно используя потоки (не создавая/убивая их при каждой операции) и выполняя некоторые из них параллельно, так что ваш процессор не будет жечь.

ОК, но когда использовать каждый из них?

в резюме: всегда используйте задачи.

задача-это абстракция, поэтому она намного проще в использовании. Я советую вам всегда пытаться использовать задачи, и если вы столкнулись с какой-то проблемой, которая заставляет вас обрабатывать поток самостоятельно (вероятно, 1% времени), то используйте потоки.

но имейте в виду, что:

  • I / O Bound: для операций с привязкой ввода-вывода (вызовы баз данных, чтение / запись файлов, API звонки и т. д.) Избегайте использования обычных задач, использовать LongRunning задач (или потоки, если вам нужно). Потому что использование задач приведет вас к пулу потоков с несколькими занятыми потоками и множеством других задач, ожидающих своей очереди принять пул.
  • CPU Bound: для операций с привязкой к ЦП просто используйте обычные задачи (которые внутренне будут использовать пул потоков) и будьте счастливы.

можно использовать Task, чтобы указать, что вы хотите сделать затем приложите что Task с Thread. так что Task был бы выполнен в этом новоиспеченном Thread а не в потоке GUI.

использовать Task с TaskFactory.StartNew(Action action). Здесь вы выполняете делегат, поэтому, если вы не использовали какой-либо поток, он будет выполняться в том же потоке (GUI thread). Если вы упомянули поток, вы можете выполнить это Task в другом треде. Это ненужная работа, потому что вы можете напрямую выполните делегат или присоедините этот делегат к потоку и выполните этот делегат в этом потоке. Так что не используйте его. это просто не нужно. Если вы намерены оптимизировать свое программное обеспечение, это хороший кандидат для удаления.

**Пожалуйста, обратите внимание на то, что Action это delegate.

в дополнение к вышеуказанным пунктам, было бы хорошо знать, что:

  1. задача по умолчанию является фоновой задачей. У вас не может быть приоритетной задачей. С другой стороны, поток может быть фоновым или передним планом (используйте свойство IsBackground для изменения поведения).
  2. задачи, созданные в пуле потоков, перерабатывают потоки, что помогает экономить ресурсы. Поэтому в большинстве случаев задачи должны быть выбором по умолчанию.
  3. Если операции выполняются быстро, это гораздо лучше использовать задача вместо потока. Для длительных операций задачи не предоставляют больших преимуществ по сравнению с потоками.

задача похожа на операцию , которую вы хотите выполнить, поток помогает управлять этой операцией через несколько узлов процесса. задача-это легкий вариант, поскольку потоковая обработка может привести к сложному управлению кодом
Я предложу читать с MSDN (лучший в мире) всегда

задание

Thread

Я обычно использую Task для взаимодействия с Winforms и простым фоновым работником, чтобы он не замораживал пользовательский интерфейс. вот пример, когда я использую Task

private async void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    await Task.Run(() => {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
    })
    buttonDownload.Enabled = true;
}

VS

private void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    Thread t = new Thread(() =>
    {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
        this.Invoke((MethodInvoker)delegate()
        {
            buttonDownload.Enabled = true;
        });
    });
    t.IsBackground = true;
    t.Start();
}

разница в том, что вам не нужно использовать MethodInvoker и более короткий код.