Ответ 1
Когда вы используете Dispatcher.BeginInvoke
, это означает, что он планирует выполнение данного действия для выполнения в потоке пользовательского интерфейса в более поздний момент времени, а затем возвращает элемент управления, чтобы позволить текущему потоку продолжать выполнение. Invoke
блокирует вызывающего абонента до завершения запланированного действия.
Когда вы используете BeginInvoke
, ваш цикл будет работать быстрее супер, так как BeginInvoke
сразу возвращается. Это означает, что вы добавляете много и много действий в очередь сообщений. Вы добавляете их намного быстрее, чем их можно обработать. Это означает, что существует много времени между тем, когда вы планируете сообщение и когда он действительно получает шанс на запуск.
Фактическое действие, которое вы используете, использует поле _number
. Но _number
очень быстро изменяется другим потоком и пока действие находится в очереди. Это означает, что он не отображает значение _number
в момент, когда вы запланировали действие, но скорее то, что оно есть после того, как оно продолжается в нем очень плотно.
Если вы используете Dispatcher.Invoke
вместо этого, это предотвращает "опережение" цикла и наличие нескольких запланированных событий, что гарантирует, что значение, которое он пишет, всегда является "текущим" значением. Кроме того, заставляя каждую итерацию цикла ждать выполнения сообщения, он делает цикл намного менее "плотным", поэтому он не может работать так быстро, как обычно.
Если вы хотите использовать BeginInvoke
, первое, что вам действительно нужно сделать, это замедлить ваш цикл. Если вы хотите, чтобы он обновлял текст каждую секунду или даже 10 мс или что-то еще, вы можете использовать Thread.Sleep
для ожидания соответствующего времени.
Затем вам нужно взять копию _number
, прежде чем передавать ее в Dispatcher
, чтобы она отображала значение в то время, когда вы его запланировали, а не во время его выполнения:
while (true)
{
if (_number++ > 10000)
_number = 0;
int copy = _number;
this.Dispatcher.BeginInvoke(new Action(() => UpdateText(copy))
, System.Windows.Threading.DispatcherPriority.Background, null);
Thread.Sleep(200);
}
private void UpdateText(int number)
{
this.Text = number.ToString();
}