Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Разница между delegate.BeginInvoke и использованием потоков ThreadPool в C#

Автор вопроса: nighthawk457Ответов: 1

В С# есть ли разница между использованием делегата для асинхронного выполнения некоторой работы (вызовом BeginInvoke()) и использованием потока ThreadPool, как показано ниже

public void asynchronousWork(object num)
    {
        //asynchronous work to be done
        Console.WriteLine(num);
    }

 public void test()
    {
        Action<object> myCustomDelegate = this.asynchronousWork;
        int x = 7;

        //Using Delegate
        myCustomDelegate.BeginInvoke(7, null, null);

        //Using Threadpool
        ThreadPool.QueueUserWorkItem(new WaitCallback(asynchronousWork), 7);
        Thread.Sleep(2000);
    }

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

  • возможный дубликат Использует ли Func‹T›.BeginInvoke ThreadPool? nothrow 27.04.2012
  • Я не уверен, был ли ваш комментарий до того, как я отредактировал свой вопрос, но я знаю, что BeginInvoke выполняет делегаты в потоках, принадлежащих пулу потоков. Мой вопрос был больше о том, есть ли какая-либо разница между явным выполнением метода в пуле потоков с использованием QueueUserWorkItem или с использованием BeginInvoke nighthawk457 27.04.2012

multithreadingthreadpool

Ответы

Ответ 1 · рейтинг 34 · Lee

Джо Даффи в своей книге Concurrent Programming on Windows (стр. 418) говорит о Delegate.BeginInvoke следующее:

Все типы делегатов по соглашению предлагают методы BeginInvoke и EndInvoke наряду с обычным синхронным методом Invoke. Хотя это хорошая функция модели программирования, вы должны держаться подальше от них, где это возможно. Реализация использует инфраструктуру удаленного взаимодействия, которая накладывает значительные накладные расходы на асинхронный вызов. Работа с очередью напрямую в пул потоков часто является лучшим подходом, хотя это означает, что вам придется самостоятельно координировать логику рандеву.

РЕДАКТИРОВАТЬ: я создал следующий простой тест относительных накладных расходов:

int counter = 0;
int iterations = 1000000;
Action d = () => { Interlocked.Increment(ref counter); };

var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
for (int i = 0; i < iterations; i++)
{
    var asyncResult = d.BeginInvoke(null, null);
}

do { } while(counter < iterations);
stopwatch.Stop();

Console.WriteLine("Took {0}ms", stopwatch.ElapsedMilliseconds);
Console.ReadLine();

На моей машине вышеуказанный тест выполняется примерно за 20 секунд. Замена вызова BeginInvoke на

System.Threading.ThreadPool.QueueUserWorkItem(state =>
{
    Interlocked.Increment(ref counter);
});

изменяет время работы на 864 мс.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы