Этот код имеет условие гонки в поле данных.Анонимный делегат DownloadDataCompleted вызывается из потока, отличного от data.Length, и в тот момент, когда вызывается DownloadDataCompleted, IsBusy становится ложным.Это гонка между двумя потоками о том, кто первым обращается к данным.Если основной поток вызывает data.Length до того, как данные заданы в потоке загрузки, вы получите исключение нулевой ссылки.Должно быть легко увидеть, если вы заставите удаление DownloadDataCompleted всегда терять гонку, добавив к нему вызов Thread.Sleep (), прежде чем он установит данные.
Состояния потока будут выглядеть следующим образом:
Main Thread Download Thread client.IsBusy
Waiting.... downloading... true
leaves waiting loop calls delegate false
calls data.Length data = e.Result
Нет способа узнать, какой поток будет запускать последнюю строку первым.На многопроцессорной машине оба могут работать одновременно.
Поскольку все это основано на времени, иногда оно будет работать, а иногда - не получится.Вам нужна какая-то синхронизация (блокировка) для всех данных, к которым обращаются многопоточные потоки.