Как временное обновление, мое тестирование показывает, что оба асинхронных обработчика событий и небольшие синхронные ожидания являются подходящими подходами. Я достигаю значительно лучшего начального ответа, делегировав только сетевую операцию Wait (.1), инициировав DispatcherInvoke (() => {txtStatus + = "WAIT .."}, а затем сразу следует Dispatch (() => {; / /}, DispatcherPriority.ApplicationIdle).
Использование асинхронного обработчика событий и IProgress (вам даже не нужен Dispatcher, просто измените связанный элемент управления) внутри сетевого вызова приводит к аналогичному обновлению прогресса, но с первоначальным ответом, который может быть неприемлемым.
Использование синхронного ожидания приводит к остановке рисования пользовательского интерфейса, из-за чего любой постепенно обновляемый индикатор выполнения выглядит очень резко.
Для меня, индикатор выполнения - это не проблема, потому что я даю оператору прямую обратную связь с WAIT .. WAIT .. WAIT .. И все, что делает индикатор выполнения, показывает, останавливаясь, насколько резервное копирование дело в том, но я сохраняю достаточно синхронного контроля, чтобы затормозить колеблющуюся осторожность. Колебание может быть прерывистым, но обученные операторы будут знать, если это предупреждение будет продолжаться, хотя неравномерно, вы включены, даже если постепенный индикатор выполнения останавливается и запускается.
И я могу обнаружить это в синхронном коде, а затем что-то сделать на лету, например, разгрузить весь сетевой вызов и затем заставить пользователя поставить в очередь и опросить.
UPDATE
async Task<List<Double>> NetworkList(IProgress<Int32> NetworkProgress)
{
List<Double> _results = new List<Double>();
foreach(var aNetwork in LotsOfNetworksCouldTakeAwhile)
{
SendPingFarAwayLand();
await Task.Delay(delay: TimeSpan.Frommilliseconds(100);
Double PingTime = GetPingTimeOrNull();
_results.Add(PingTIme);
NetworkProgress.Report( aNetwork.NetworkID );
}
}
async btnClick
{
TimeSpan IDLE_LONG_ENOUGH_SO_DISPATCHER_UPDATES_UI = TimeSpan.FromMilliseconds(50);
txtStatus += "WORKING...";
await Task.Delay(delay: IDLE_LONG_ENOUGH_SO_DISPATCHER_UPDATES_UI);
Task<List<Double>> results = await NetworkList(_Progress);
dependencyObject1.ObservableList1.Add(results);
return;
}
Кажется, это работает по крайней мере на моем компьютере. Достаточно около 50 миллисекунд, чтобы гарантировать, что диспетчер немедленно обработает ваше последнее сообщение «РАБОТАЕТ ...». Если вы этого не сделаете, вы можете нажать диспетчер в цикле повышения, но, возможно, нет, и он запустится в LongNetworkList, и может пройти полсекунды, прежде чем вы даже увидите, что что-то происходит.
Это похоже на то, хотите ли вы, чтобы капитан команды спринта поразил секундомер или побежал с вами. Задержка в 50 миллисекунд даже для начала работы кажется большой, если вы пытаетесь пропинговать две сети на 10 мс. Но если у вас есть хотя бы один аберрант, который сразу же забирает все ожидаемые 100 мс, и STILL ничего не возвращает, чтобы вы могли сообщить о достигнутом прогрессе, было бы неплохо вывести что-нибудь на экран.
Слава Клири, я перехожу на Reactive.NET сразу после обеда.