Предполагая, что uiScheduler
является планировщиком, который будет делегировать вызовы потоку пользовательского интерфейса, я бы сказал, что функционально использование этих двух безразлично (за исключением того, что вызов Control.Invoke будет блокироваться до завершения вызова, тогда как вызов Task
не будет, однако, вы всегда можете использовать Control.BeginInvoke
, чтобы сделать их семантически эквивалентными).
С семантической точки зрения я бы сказал, что использование Control.Invoke(PaintDelegate)
- гораздо лучший подход; при использовании Task
вы делаете неявное объявление о том, что хотите выполнить единицу работы, и обычно эта единица работы имеет контекст планирования вместе с другими единицами работы, именно планировщик определяет, как эта работа делегируется (как правило, он многопоточный, но в этом случае он маршалируется в поток пользовательского интерфейса). Следует также сказать, что нет четкой связи между uiScheduler
и Control
, которая связана с потоком пользовательского интерфейса, что вызов должен быть выполнен один (как правило, они все одинаковы, но возможно иметь несколько UI темы, хотя и очень редко).
Тем не менее, при использовании Control.Invoke
цель того, что вы хотите сделать, ясна: вы хотите перенаправить вызов в поток пользовательского интерфейса, на который Control
отправляет сообщения, и этот вызов прекрасно это показывает.
Я думаю, что лучший вариант - использовать экземпляр SynchronizationContext
; он абстрагирует тот факт, что вам нужно синхронизировать вызовы с этим контекстом, в отличие от двух других вариантов, которые либо неоднозначны относительно цели в вызове (Task
), либо очень специфичны в том, как это делается (Control.Invoke
). * * тысячу двадцать-один