c# - Cross-thread exception when trying to update image from byte array -
i working on application shows 2 videos side-by-side (unfortunately custom format).
when try display video frames, "cannot access object because different thread owns it"-exception, though thought calling dispatcher fix that.
it seems people have had similar problems when using bitmapimages or similar, , solve problem via freezing image, in case, receive byte array, not seem have freeze-method.
this problematic code (which called async method):
private void showvideo(string filename) { colorvideo video = new colorvideo(filename); // colorvideo reads frames disk writeablebitmap image = new writeablebitmap(video.width, video.height, 96, 96, pixelformats.bgr32, null); // set image source image frame in ui this.dispatcher.begininvoke((action)delegate { this.imageframe.source = image; }); (int i=0; < video.length, i++) { byte[] framebytes = video.getframe(i); // following line throws exception. // wrapping line inside call dispatcher doesn't // cross-thread exception regardless image.writepixels(new int32rect(0,0,video.width,video.height),framebytes, video.width*4,0); } } now, suspect approach may not ideal, anyway. want able run showvideo method in background , have update image shown 30 times second. how can better?
note first creating bitmap, issuing begininvoke+setsource operations dispatcher, , write pixels.
this leaves race: dispatcher can first set bitmap source, , loop may run , try modify pixels. since loop runs in background thread, writepixels may throw. have not checked, guess.
so, first try:
your-for-loop { create-a-bitmap get-frame write-pixels // xxx this.dispatcher.begininvoke((action)delegate { this.imageframe.source = image; }); } so moving start of dispatcher block may remove problem, ensure loop not write bitmap pushed ui.
in setup, can still add "freeze" @ xxx marks, allow wpf skip intermediate copies of bitmaps, not single copy done during rendering. however, adding freeze not @ fact loop allocate , throw out new bitmaps.
the fact of creating them create pressure on memory , gc. not bitmaps created, must periodically found , removed gc. can circumvent little creating two bitmaps , reusing them flipping odd-even:
create-bitmap-1 create-bitmap-2 your-for-loop { get-frame if frame-number odd write-pixels bitmap-1 else write-pixels bitmap-2 this.dispatcher.begininvoke((action)delegate { if frame-number odd this.imageframe.source = image1; else this.imageframe.source = image2; }); } note important thing: when using way, cannot freeze bitmaps wpf in caching , cut number of intermediate copies. not want make them cacheable, , need bitmaps modifiable. slow down renderer and/or compositor thread, lower pressure on gc , cpu in overall.
Comments
Post a Comment