Сначала необходимо выполнить вызов CheckAccess () для Dispatcher, чтобы выяснить, находитесь ли вы в потоке пользовательского интерфейса и, следовательно, способны обновлять элемент пользовательского интерфейса.
Вот вспомогательная функция, которую я написал для обновления моих комбинированных списков в WPF, вы можете легко адаптировать ее для соответствия элементу управления Image, и это хороший пример вызова CheckAccess:
private void UpdateComboDataSource<T>(ComboBox ctrl, IEnumerable<T> datasource, string displayPath, string valuePath)
{
if (ctrl == null)
throw new ArgumentNullException("Control to be bound must not be null");
//check if we are on the control's UI thread:
if (ctrl.Dispatcher.CheckAccess())
{
//we have full access to the control, no threading issues, so let's rip it up and databind it
datasource = datasource.OrderBy(x => x);
if (displayPath != null && ctrl.DisplayMemberPath == null)
ctrl.DisplayMemberPath = displayPath;
if (valuePath != null && ctrl.SelectedValuePath == null)
ctrl.SelectedValuePath = valuePath;
ctrl.ItemsSource = datasource;
}
else
{
//we don't have full access to the control because we are running on a different thread, so
//we need to marshal a call to this function from the control's UI thread
UpdateComboDataSourceDelegate<T> del = new UpdateComboDataSourceDelegate<T>(this.UpdateComboDataSource);
ctrl.Dispatcher.BeginInvoke(del, ctrl, datasource, displayPath, valuePath);
}
}
private delegate void UpdateComboDataSourceDelegate<T>(ComboBox ctrl, IEnumerable<T> dataSource, string displayPath, string valuePath);
Таким образом, функция проверяет, имеет ли она доступ, назначает ли она источник данных. Если это не так, то он перезванивает сам, но на этот раз в контексте потока пользовательского интерфейса.
Вероятно, существует более лаконичный способ кодирования создания делегата, но это не очень хорошо для людей, пытающихся понять пример, отсюда и явное определение делегата.