Как скопировать и обработать WriteableBitmap в отдельном потоке?

В моем приложении kinect есть основной поток, который отвечает за связь между потоком пользовательского интерфейса и другими потоками. Я не могу сделать копию WriteableBitmap, сгенерированную из kinect, и передать это изображение WriteableBitmap в отдельный поток с обработкой EmguCV. Я пробовал все: Clone, CloneCurrentValue, BlockingCollection, но всегда были некоторые проблемы, такие как:

Вызывающий поток не может получить доступ к этому объекту, так как другой поток владеет

Или обработка данных неправильная. Это основной цикл в моем приложении;

WritableBitmap color; WritableBitmap depth; 
while (true) {          
    kinect.updateFrames();                
    ctrlMainWindow.Dispatcher.BeginInvoke(new Action(() =>
    {
       color = kinect.video.getBitmapColor();                   
       depth = kinect.video.getBitmapDepth();
    }));
    updateDetectors(color,depth); // Other thread
 }

person Dariusz Filipiak    schedule 02.08.2015    source источник


Ответы (1)


Без хорошего, минимального, полного примера кода, надежно воспроизводящего проблему , трудно, если вообще возможно, узнать, в чем именно заключается проблема, не говоря уже о том, как ее исправить. Это сказало

Как вы, вероятно, знаете, WriteableBitmap наследует DispatcherObject, и доступ к нему должен осуществляться только внутри потока диспетчера, которому он принадлежит.

Предположительно, вызов kinect.updateFrames() — это то, что фактически создает объекты, поэтому одним из очевидных решений будет вызов этого метода внутри вызываемого анонимного метода, а не непосредственно перед ним.

Если по какой-то причине это невозможно, альтернативой может быть замораживание растровых изображений перед попыткой их использования в неправильном потоке. Например.:

kinect.updateFrames();                
color = kinect.video.getBitmapColor();
depth = kinect.video.getBitmapDepth();

color.Freeze();
depth.Freeze();

ctrlMainWindow.Dispatcher.BeginInvoke(new Action(() =>
{
    // use color and depth in other thread
}));

За исключением любого из этого, вы можете напрямую обращаться к данным растровых изображений (например, CopyPixels() или Lock()/BackBuffer) и использовать эти данные для создания новых растровых изображений в правильном потоке.

Если ничего из вышеперечисленного не окажется для вас полезным, предоставьте хороший пример кода, как описано в приведенной выше ссылке.

person Peter Duniho    schedule 03.08.2015