Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
707 views
in Technique[技术] by (71.8m points)

c# - How to edit a WritableBitmap.BackBuffer in non UI thread?

My application runs CPU-heavy algorythms to edit an Image placed at a WPF window. I need the edition to be done in a background thread. However trying to edit the BackBuffer of WritableBitmap in non UI thread throws InvalidOperationException.

    private WriteableBitmap writeableBitmap;

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        // Create WritableBitmap in UI thread.
        this.writeableBitmap = new WriteableBitmap(10, 10, 96, 96, PixelFormats.Bgr24, null);
        this.image1.Source = this.writeableBitmap;

        // Run code in non UI thread.
        new Thread(
            () =>
            {
                // 'Edit' bitmap in non UI thread.
                this.writeableBitmap.Lock(); // Exception: The calling thread cannot access this object because a different thread owns it.

                // ... At this place the CPU is highly loaded, we edit this.writeableBitmap.BackBuffer.

                this.writeableBitmap.Unlock();
            }).Start();
    }

I have read dozens of manuals, all of them tells me to do the BackBuffer edition in UI thread (i.e MSDN).

How to edit the WritableBitmap.BackBuffer in a non UI thread without any useless buffer copying/cloning?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

MSDN suggests writing to the backbuffer in a background thread. Only certain pre- and post update operations need to be carried out on the UI thread. So while the background thread is doing the actual updating, the UI thread is free to do other things:

        //Put this code in a method that is called from the background thread
        long pBackBuffer = 0, backBufferStride = 0;
        Application.Current.Dispatcher.Invoke(() =>
        {//lock bitmap in ui thread
            _bitmap.Lock();
            pBackBuffer = (long)_bitmap.BackBuffer;//Make pointer available to background thread
            backBufferStride = Bitmap.BackBufferStride;
        });
        //Back to the worker thread
        unsafe
        {
            //Carry out updates to the backbuffer here
            foreach (var update in updates)
            {
                long bufferWithOffset = pBackBuffer + GetBufferOffset(update.X, update.Y, backBufferStride);
                *((int*)bufferWithOffset) = update.Color;
            }
        }
        Application.Current.Dispatcher.Invoke(() =>
        {//UI thread does post update operations
            _bitmap.AddDirtyRect(new System.Windows.Int32Rect(0, 0, width, height));
            _bitmap.Unlock();
        });

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...