Вы можете использовать потоки, но должны использовать Dispatcher
для доступа к элементам пользовательского интерфейса.Диспетчер должен выполнить только ту часть, где вы передаете элемент в UserControl
.
Application.Current.Dispatcher.BeginInvoke(new Action(() => AddItem()));
BeginInvoke
- это асинхронный вызов, который не будет блокировать выполнение следующего кода.
Редактировать: Я все еще не уверен на 100%, если я полностью понял идею вашего приложения, но сделал небольшой пример, который демонстрирует, как вы можете использовать потоки и элементы пользовательского интерфейса.
Я сделал Window
(это будет ваш UserControl
), который содержит Button
и ListBox
.При нажатии Button
запускается поток, который обрабатывает некоторые элементы.В моем случае это просто добавляет некоторые тексты в список, я добавил Thread.Sleep(1000)
, чтобы имитировать обработку большого количества материала.Когда текст подготовлен, он будет добавлен в ObservableCollection
, что должно быть сделано потоком пользовательского интерфейса (Dispatcher
).Ничто не блокирует пользовательский интерфейс, кроме этого добавления, и это делается очень быстро.Вы также можете запускать несколько потоков одновременно.
Это код для Window
(сам Window
содержит только Button
и ListBox
):
public partial class MainWindow : Window
{
private ObservableCollection<string> textList;
public MainWindow()
{
textList = new ObservableCollection<string>();
InitializeComponent();
btnStartWork.Click += BtnStartWorkClick;
lstTextList.ItemsSource = textList;
}
private void BtnStartWorkClick(object sender, RoutedEventArgs e)
{
Thread myThread;
ThreadStart myThreadDelegate = DoWork;
myThread = new Thread(myThreadDelegate);
myThread.SetApartmentState(ApartmentState.STA);
myThread.Start();
}
private void DoWork()
{
for (int i = 0; i < 5; i++)
{
string text = string.Format("Text {0}", i);
// block the thread (but not the UI)
Thread.Sleep(1000);
// use the dispatcher to add the item to the list, which will block the UI, but just for a very short time
Application.Current.Dispatcher.BeginInvoke(new Action(() => textList.Add(text)));
}
}
}