Ця стаття є дзеркальною статтею машинного перекладу, будь ласка, натисніть тут, щоб перейти до оригінальної статті.

Вид: 42759|Відповідь: 5

[Джерело] Чому .net/c# Завдання повільніші за Thread?

[Копіювати посилання]
Опубліковано 03.05.2017 16:40:28 | | | |
.NET 4 містить новий простір імен System.Threading.Tasks, який містить класи, що абстрагують функціональність потоків. Використовуйте ThreadPool у фоновому режимі. Завдання — це робота підрозділу, яку слід виконати. Робота цього пристрою може виконуватися в окремому потоці або завдання запускатися синхронно, що вимагає очікування основного налаштуваного потоку. Використання завдань дає не лише рівень абстракції, а й дає великий контроль над основними потоками.
Завдання пропонують велику гнучкість у плануванні необхідної роботи. Наприклад, ви можете визначити безперервне завдання — яку роботу слід виконати після завершення завдання. Це може стати вирішальною різницею між успішним і неуспішним завданням. Крім того, завдання можна організовувати за ієрархією. Наприклад, батьківське завдання може створити нове дочірнє завдання. Це створює залежність, і якщо скасувати батьківське завдання, його дочірнє завдання також буде скасовано.


Сьогодні популярно використовувати методи виконання завдань, і це висока продуктивність, і я не знаю, яка саме продуктивність завдань.

Я сам тестував Task і Thread, і відчуваю, що Task дуже повільний, що суттєво впливає на продуктивність, а тестовий код виглядає так:

Ми повторюємо метод 1000 разів, потім метод блокується на 100 мілісекунд, і результат тесту виглядає так:



Результат:
Виконання потоку займає 188 мілісекунд
Виконання завдання займає 14 671 мілісекунду


Різниця у швидкості між ними становить 78 разів!!

Завдання дуже повільно, не знаю, чому це відбувається, чи щось не так із моїм тестовим кодом чи що? Сподіваюся, ви зможете пояснити, чому так відбувається...




Попередній:Надсилайте повідомлення ASP.NET Core
Наступний:C# Паралельні обчислення Parallel.For&Parallel.For
 Орендодавець| Опубліковано 13.10.2020 10:47:17 |
tongli1996218 Опубліковано 2020-10-13 09:34
Щоб забезпечити той самий код, що й у Thread, моя операція — наступний код, а наведений вище — псевдокод
P.S.: Просто зателефонуй на Завдання. Затримка без додавання...

Так, дякую

Час виконання завдання: 117.0357

Ви можете змінити код наступним чином:

Task.Run замінює Task.Factory.StartNew, оскільки автоматично розпаковує внутрішні завдання.
Завдання.ЗачекайтеВсе чекає на зовнішнє завдання замість внутрішнього. Використання Task.Run не має вкладених завдань.


Дивлячись на документацію msdn, можна побачити, що метод Task.Delay Method створює завдання, яке завершується через певну кількість мілісекунд. (Насправді, буде створено новий поток, і чекатиме, щоб чекати виконання завдання, я не впевнений, чи правильно розумію)

Вхід за гіперпосиланням видно.

Крім того, існує різниця між завданням і порожнечою

Завдання повертає асинхронний метод, який може чекати
Асинхронний метод повернення порожнечі не може чекати, він працює асинхронно, ви не можете знати, коли це зроблено, не можна відстежувати стан цієї асинхронної операції.


Посилання:

Вхід за гіперпосиланням видно.
Вхід за гіперпосиланням видно.

Підсумовуючи: є проблема з кодом, я не повинен використовувати Thread.Sleep у межах методу Завдання
Опубліковано 21.07.2020 13:09:29 |
У мене сьогодні була така ж проблема: я використовую багатопотокове шифрування для AES, Task набагато повільніший за Thread!!
Чи знайшов орендодавець причину?
Опубліковано 12.10.2020 19:24:48 |
Цей допис востаннє редагувався tongli1996218 12.10.2020, 19:43

Після тестування коду власника, коли програма запускається і запускається кілька разів, час виконання завдання продовжує зменшуватися, і на моєму комп'ютері він зменшується до меншого, ніж Thread, і Thread стабільний у цей час.

Пізніше було встановлено, що метод Thread.Sleep(100) негативно впливав на Завдання, але не на Thread, і Thread.Sleep(100) можна було замінити іншою тривалою перевіркою програм, такою як числове самододавання або очікування Task.Delay(100).

P.S.: Thread.Sleep завершує поточний час слайзингу потоку після виклику, наприклад, Thread.Sleep(0) завершить поточний час слайзингу потоків і перенесе його в інші потоки для запуску. Всередині завдання знаходиться пул потоків, який може оптимізувати перемикання контексту потоків і зменшити час втрат процесора (особливо для багатоядерної оптимізації CPU), тоді як Thread.Sleep (100) порушує логіку перемикання початкового пулу потоків завдання, спричиняючи значні втрати часу процесора

Якщо замінити Thread.Sleep(100) на waitit Task.Delay(100), ви побачите, що споживання часу завдання перевищує 100 мілісекунд, як показано нижче:
private void TaskTest()
{
        Thread.Sleep (100);
         ... Виконай дію
}
Замінено на
private async void TaskTest()
{
      чекати на завдання. Затримка (100);
      ... Виконання займає понад 100 мілісекунд, що відповідає оригінальному Thread.Sleep(100) для Thread
}




 Орендодавець| Опубліковано 12.10.2020 22:53:05 |
tongli1996218 Опубліковано 2020-10-12 19:24
Після тестування коду власника, коли програма запускається, час виконання завдання продовжує зменшуватися після кількох запусків, а на моєму комп'ютері він зменшується до меншого рівня Thread...

Я пробував змінити його на код так:
Завдання.Затримка(100000);

Час виконання завдання:14.1306 мс, загальний час дійсно дуже короткий, однак я виявив, що метод, викликаний Задачею, не завершив виконання.
Опубліковано 13.10.2020 09:34:33 |
Цей допис востаннє відредаговано tongli1996218 13.10.2020 09:40
Опубліковано 2020-10-12 22:53
Я пробував змінити його на код так:
Завдання.Затримка (100000);

Щоб забезпечити той самий код, що й у Thread, моя операція — наступний код, а наведений вище — псевдокод
P.S.: Просто викликайте waitit Task.Delay, а потім не додайте код, потік, відкритий завданням, повертається негайно, щоб забезпечити симуляцію обчислювальних обмежень, яку можна використовувати для (int a = 0; а< 1000000; ++a){}; Натомість такі методи

приватний асинхронний статичний порожній TaskTest()
        {
            чекати на завдання. Затримка (100000);
             Interlocked.Increment (запуск референта);    Замок, але верхні витрати менші
            if(run == j)
             {
                секундомір. Stop(); Припиніть моніторинг
                TimeSpan timespan = секундомір. Минуло;  Отримує загальний час, виміряний поточним екземпляром
                Console.WriteLine("Час виконання завдання:" + часовий проміжок. TotalMilliseconds); Загальна кількість мілісекунд
              }
        Витрачений час також дуже короткий


Застереження:
Усе програмне забезпечення, програмні матеріали або статті, опубліковані Code Farmer Network, призначені лише для навчання та досліджень; Вищезазначений контент не повинен використовуватися в комерційних чи незаконних цілях, інакше користувачі несуть усі наслідки. Інформація на цьому сайті надходить з Інтернету, і спори щодо авторських прав не мають до цього сайту. Ви повинні повністю видалити вищезазначений контент зі свого комп'ютера протягом 24 годин після завантаження. Якщо вам подобається програма, будь ласка, підтримуйте справжнє програмне забезпечення, купуйте реєстрацію та отримайте кращі справжні послуги. Якщо є будь-яке порушення, будь ласка, зв'яжіться з нами електронною поштою.

Mail To:help@itsvse.com