Ну, BackgroundWorker - не единственный вариант, который у вас есть, но для того, чтобы выполнить то, что вы хотите, вам все равно нужно использовать несколько потоков или асинхронных операций, чтобы не блокировать, пока вы ожидаете завершения длительных операций.
И, поскольку WPF требует, чтобы весь код, обращающийся к пользовательскому интерфейсу, выполнялся в одном и том же потоке, вам необходимо выполнить некоторое переключение контекста при вызове или доступе к данным или коду в потоке пользовательского интерфейса. Чтобы обеспечить выполнение вызова в потоке пользовательского интерфейса в WPF, используйте класс диспетчера .
Другой простой способ сохранить отзывчивость пользовательского интерфейса - поставить рабочий элемент в очередь в пуле потоков, что выполняется с помощью класса ThreadPool.
// assuming the the following code resides in a WPF control
// hence "this" is a reference to a WPF control which has a Dispatcher
System.Threading.ThreadPool.QueueUserWorkItem((WaitCallback)delegate{
// put long-running code here
// get the result
// now use the Dispatcher to invoke code back on the UI thread
this.Dispatcher.Invoke(DispatcherPriority.Normal,
(Action)delegate(){
// this code would be scheduled to run on the UI
});
});
Как всегда, существует более одного способа снятия шкуры с кошки, но помните, что у каждой техники есть свои преимущества и недостатки. Например, описанный выше метод может быть полезен, поскольку в нем не так много служебной информации, но в некоторых случаях это может быть не самый эффективный способ.
Доступны и другие варианты, включая использование BeginXXX - EndXXX методов классов, которые вы используете, если они предоставляют какие-либо (например, SqlCommand класс имеет BeginExecuteReader EndExecuteReader ). Или, используя методы XXXAsync, если классы имеют это. Например, класс System.Net.Sokets.Socket имеет ReceiveAsync и SendAsync.