简体   繁体   English

C#线程化位图对象/ PictureBox

[英]C# Threading Bitmap objects/PictureBox

I have some code to display video-like graphics of points moving around. 我有一些代码来显示视频样点移动的图形。

I am writing the points to a bitmap, and placing it on a picturebox. 我将这些点写入位图,并将其放置在图片框上。

The graphics computation has to be done on its own thread. 图形计算必须在其自己的线程上完成。 The graphics work fine as long as you don't move the window around "too" much. 只要您不要将窗口移得太多,图形就可以正常工作。

I'm using winforms. 我正在使用winforms。 When I run the code, and move the window around wildly, I SOMETIMES get the following errors: 当我运行代码并疯狂地移动窗口时,有时会出现以下错误:

@ this.Invoke(d, new object[ ] { bmp }); @ this.Invoke(d,new object [] {bmp}); "Cannot access a disposed object. Object name: 'Form1'." “无法访问已处置的对象。对象名称:'Form1'。”

@ gfx.DrawImage(bmpDestination, new Point()); @ gfx.DrawImage(bmpDestination,new Point()); "Object is currently in use elsewhere." “对象当前正在其他地方使用。”

Here is the code: 这是代码:

private void button2_Click(object sender, EventArgs e)
        {
            Thread demoThread = new Thread(new ThreadStart(ThreadProcSafe));

            demoThread.Start();
        }

        private void ThreadProcSafe()
        {
            creategraphics();
        }

        private void creategraphics()
        {

                Bitmap bmpDestination = new Bitmap(988, 588);
                Bitmap bmp = new Bitmap(988, 588);


                for (int i = 0; i < numtimesteps; i++)
                {
                    bmp = GraphingUtility.create(apple, i, 988, 588, -30, 30, -30, 30);

                        using (Graphics gfx = Graphics.FromImage(bmp))
                        {
                            gfx.DrawImage(bmpDestination, new Point());
                        }
                        bmpDestination = bmp;
                        updateimage(bmp);
                }
        }

        delegate void graphicscallback(Bitmap bmp);

        private void updateimage(Bitmap bmp)
        {
                if (pictureBox1.InvokeRequired)
                { 
                   graphicscallback d = new graphicscallback(updateimage);
                   this.Invoke(d, new object[] { bmp });
                }
                else
                { 
                    pictureBox1.Image = bmp;
                    pictureBox1.Refresh();  
                }
        }

There are problems using GDI objects across threads. 跨线程使用GDI对象存在问题。

Look at Hans' double-clone suggestions in this thread . 此主题中查看Hans的双克隆建议。

Cannot access a disposed object. 无法访问已处置的对象。 Object name: 'Form1 对象名称:'Form1

You get this because you don't do anything to stop the thread when the user closes the form. 之所以会这样,是因为您在用户关闭表单时不执行任何操作来停止线程。 You'll have to keep the form alive until you know that the thread is dead. 您必须保持活动状态,直到您知道线程已死。 Pretty hard to do reliable, check this answer for a solution. 很难做到可靠,请查看此答案以获取解决方案。

As an aside, calling InvokeRequired is an anti-pattern. 顺便说一句,调用InvokeRequired是一种反模式。 You know that you are making the call from a worker thread. 知道您正在通过工作线程进行调用。 If InvokeRequired would return false then there's something really wrong. 如果InvokeRequired将返回false,则说明确实存在错误。 Don't bother, call Invoke() directly. 不要打扰,直接调用Invoke()。

Object is currently in use elsewhere 当前在其他地方使用对象

It is an exception raised by GDI+ (Graphics) when it sees that two threads are trying to access a bitmap at the same time. 当看到两个线程试图同时访问位图时,这是GDI +(图形)提出的异常。 It isn't obvious in your snippet but I can't see what GraphingUtility.create() does. 这在您的代码段中并不明显,但是我看不到GraphingUtility.create()的作用。 Make sure it creates a new bitmap, not return an existing one. 确保它创建一个新的位图,而不返回现有的位图。 Because that will bomb when your thread writes to it again and the picture box repaints itself at the same time. 因为这将在您的线程再次向其写入并且图片框同时重新绘制自身时炸弹。 The bmp constructor you use above it doesn't do anything. 您在上面使用的bmp构造函数没有任何作用。

Your PictureBox.Image assignment is forgetting to dispose the old one. 您的PictureBox.Image分配忘记处理旧的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM