Я думаю, что это во многом зависит от числа, которое Вы планируете на включении. Если и 'b' не будет 'хорошее' число тогда, то Вы, вероятно, получите значение, которое не завершается, который невозможно сохранить и если C# BigDecimal ведет себя вообще как Java BigDecimal, это, вероятно, выдает исключение в таком случае.
Код - это железная дорога, а нить - это поезд. Когда поезд движется по железной дороге, он выполняет код.
BeginMyMethod
выполняется основным потоком. Если вы заглянете внутрь BeginMyMethod
, он просто добавит делегата MyMethod
в очередь ThreadPool
. Фактический MyMethod
выполняется одним из составов группы поездов. Подпрограмма завершения, которая вызывается при выполнении MyMethod
, выполняется тем же потоком, который выполнил MyMethod
, а не вашим основным потоком, выполняющим остальной код. Пока поток пула потоков занят выполнением MyMethod
, основной поток может либо использовать какую-либо другую часть железнодорожной системы (выполнять другой код), либо просто спать, ожидание, пока не загорится определенный семафор.
Следовательно, не существует такой вещи, как IAsyncResult
, «знающий», когда вызывать подпрограмму завершения, вместо этого подпрограмма завершения - это просто делегат, вызываемый потоком пула потоков сразу после его завершения, выполняя MyMethod
.
Надеюсь, вы не возражаете против несколько детской аналогии с поездом, я знаю, что она мне не раз помогала при объяснении многопоточности людям.
Асинхронные методы работают с использованием .NET ThreadPool
. Они перенесут работу в поток ThreadPool
(потенциально создавая его при необходимости, но обычно просто повторно используя его), чтобы работать в фоновом режиме.
В вашем случае вы можете делать то, что вы однако следует понимать, что пул потоков
имеет ограниченное количество потоков, с которыми он будет работать. Вы собираетесь создать свою работу в фоновых потоках, и первый будет запущен немедленно, но через некоторое время они встанут в очередь и не будут работать, пока «задачи» не будут выполнены полностью. В результате будет казаться, что нити будут длиться все дольше и дольше.
Однако ваши критерии секундомера несколько ошибочны. Вы должны измерить общее время, необходимое для выполнения N задач, а не N раз для выполнения одной задачи.
Суть в том, что вызов Begin
ставит в очередь запрос на выполнение вашего метода. Метод фактически выполняется в ThreadPool, который представляет собой набор рабочих потоков, предоставляемых средой выполнения.
Пул потоков - это фиксированный набор потоков для обработки асинхронных задач, когда они помещаются в очередь. Это объясняет, почему вы видите, что время выполнения занимает все больше и больше - каждый из ваших методов может выполняться примерно за одно и то же время, но они не запускаются до тех пор, пока не будут выполнены все предыдущие методы в очереди.
Для отслеживания продолжительности времени требуется для фактического выполнения асинхронного метода, вы должны запускать и останавливать таймер в начале и в конце вашего метода.
Вот документы для класса ThreadPool ,
Возможно, большая часть времени выполнения происходит до BeginMyMethod ()
. В этом случае ваше измерение будет слишком низким. Фактически, в зависимости от API, BeginMyMethod ()
может вызвать обратный вызов перед выходом из самого стека. Перемещение вызова StopWatch.Start ()
должно тогда помочь.