В чем разница между task и thread?

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

8 ответов


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

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

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


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

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

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


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

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

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

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

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

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

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

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

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


нить

голая металлическая вещь, вам, вероятно, не нужно ее использовать, вы, вероятно, можете использовать LongRunning задача и воспользоваться преимуществами параллельной библиотеки 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). Если вы упомянули поток, вы можете выполнить это Task в другом треде. Это ненужная работа, потому что вы можете напрямую выполните делегат или присоедините этот делегат к потоку и выполните этот делегат в этом потоке. Так что не используй его. в этом нет необходимости. Если вы намерены оптимизировать свое программное обеспечение, это хороший кандидат для удаления.

* * обратите внимание, что Action это delegate.


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

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

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

задание

нить


Я обычно использую 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 и более короткий код.