Вам нужно сделать две вещи:
- Заморозьте ваш BitmapImage, чтобы его можно было перенести в поток пользовательского интерфейса, затем
- Используйте Dispatcher для перехода к потоку пользовательского интерфейса, чтобы установить GeneratedImage
Вам потребуется доступ к диспетчеру потока пользовательского интерфейса из потока генератора. Самый гибкий способ сделать это - захватить значение Dispatcher.CurrentDispatcher в основном потоке и передать его в поток генератора:
public void InitiateGenerateImages(List<Coordinate> coordinates)
{
var dispatcher = Dispatcher.CurrentDispatcher;
var generatorThreadStarter = new ThreadStart(() =>
GenerateImages(coordinates, dispatcher));
...
Если вы знаете, что будете использовать это только в работающем приложении, и что у приложения будет только один поток пользовательского интерфейса, вы можете просто позвонить Application.Current.Dispatcher
, чтобы получить текущий диспетчер. Недостатки:
- Вы теряете возможность использовать модель представления независимо от созданного объекта Application.
- В вашем приложении может быть только один поток пользовательского интерфейса.
В потоке генератора добавьте вызов Freeze после генерации изображения, затем используйте Dispatcher для перехода к потоку пользовательского интерфейса для установки изображения:
var backgroundThreadImage = GenerateImage(coordinate);
backgroundThreadImage.Freeze();
dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
GeneratedImage = backgroundThreadImage;
}));
Разъяснение
В приведенном выше коде очень важно, чтобы Dispatcher.CurrentDispatcher был доступен из потока пользовательского интерфейса, а не из потока генератора. У каждого потока есть свой Диспетчер. Если вы вызовете Dispatcher.CurrentDispatcher из потока генератора, вы получите его Dispatcher вместо того, который вам нужен.
Другими словами, вы должны сделать это:
var dispatcher = Dispatcher.CurrentDispatcher;
var generatorThreadStarter = new ThreadStart(() =>
GenerateImages(coordinates, dispatcher));
а не это:
var generatorThreadStarter = new ThreadStart(() =>
GenerateImages(coordinates, Dispatcher.CurrentDispatcher));