Ответ 1
Джо Даффи в своей книге Concurrent Programming on Windows
(стр. 418) говорит об этом Delegate.BeginInvoke
:
Все типы делегатов по соглашению предлагают метод BeginInvoke и
EndInvoke
наряду с обычным синхронным методомInvoke
. Хотя это хорошая функция модели программирования, вы должны держаться подальше от них, где это возможно. В реализации используется удаленная инфраструктура, которая накладывает значительные ажурные накладные расходы на асинхронный вызов. Работа с очередью в пуле потоков напрямую часто является лучшим подходом, хотя это означает, что вы должны сами координировать логику рандеву.
EDIT: я создал следующий простой тест относительных накладных расходов:
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 мс.