刷新PictureBox导致ArgumentException参数无效

时间:2015-06-25 15:58:48

标签: c# winforms thread-safety

我不能为我的生活弄清楚这一点。我正在修改PictureBox指向的位图。基本上有人有人在图片框中拖动图像,图像会更新,因此看起来像是在图片框中拖动。在刷新图片框时会发生什么,我在Application.Run行上得到一个ArgumentException参数无效错误,所以我花了一些时间来弄清楚究竟是什么造成了这个因为异常中没有更多信息。

我创建了一个派生自picturebox并覆盖onpaint方法的类。它还有一个方法RefreshImage来调用自身并刷新自己

如果我不刷新图片框,我不会收到此错误,但图片框图片永远不会更新

我在后面运行一个主循环来更新逻辑。逻辑是拖动鼠标时,图像偏移量会更新。

循环完成逻辑后,它会尝试刷新图片框。这是我发现当我注释掉刷新线时,我没有问题,但图片框永远不会更新。我已经为自定义图片框类添加了一个方法,名为UpdateImage,它调用自身然后刷新。

重写的onpaint方法从自定义循环线程获取逻辑,并根据后端循环线程更新的偏移量更新位图

主要表单是在主线程上创建的,并且图片框也是在主线程上创建的,我已经检查了

调用正常工作,后端线程在刷新图片框时调用主线程

注释掉刷新行会使错误消失,但无法看到图片框更新

对于更好的方法或错误的解决方案,是否有任何建议?

这里是来自图片类的一部分

    public class PictureBoxEX : PictureBox
    {
        public int m_xoffset = 0;
        private Bitmap m_picture;
        public PictureBoxEX()
        {
            m_picture = new Bitmap(690, 600);
            this.Image = m_picture;
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            DrawBitmaps(); // updates the m_picture with another bitmap only in this class
            Graphics g = pe.Graphics;
            g.DrawImage(this.m_picture, new Point(0, 0));
        }
        public void RefreshImage()
        {
            if(this.InvokeRequired)
            {
                MethodInvoker d = new MethodInvoker(RefreshImage);
                this.Invoke(d);
            }
            else
            {
                this.Refresh();
            }
        }
    }

继承了主循环的想法

    private MainForm m_MainWindow; // derrives from Form

    private void MainThread()
    {
        int currTime = System.Environment.TickCount;
        int lastTime = currTime;
        while (Running)
        {
            currTime = System.Environment.TickCount;
            m_MainWindow.Update(currTime, lastTime);
            lastTime = currTime;

            Thread.Sleep(10);
        }
    }

下载主窗口中的更新方法类型

PictureBoxEx m_LeftPictureBox;

public void Update(int currTime, int lastTime)
    {
        // do logic (all the logic is only working with primitive types, nothing to do with actual bitmaps
        this.m_LeftPictureBox.RefreshImage(); // if i comment this out, i will not get the exception, but it will not update the picturebox
    }
}

还有一件事,为什么当主窗体刷新时,图片框没有刷新?或者可能是主要形式不令人耳目一新?我确定如果是这种情况我会看到光标没有被清除。我在自定义图片框类的onpaint方法中放置了一个断点,它在第一次创建时只调用一次,但之后没有,所以我必须手动刷新它。

编辑: 不确定我能提供多少代码来帮助解决这个问题,但如果我从后台线程中调用此函数(此函数在我制作的表单类中),我几乎立即得到相同的异常。异常发生在this.Refresh()和主线程上(因此在调用之后)。尽管它处于try-catch块中,但异常仍然表示它未被捕获并关闭了我的应用程序

    public void InvokeRefresh()
    {
        if (this.InvokeRequired)
        {
            RefreshDelegate d = new RefreshDelegate(InvokeRefresh);
            this.Invoke(d, null);
        }
        else
        {
            try
            {
                this.Refresh();
            }
            catch { }
        }
    }

1 个答案:

答案 0 :(得分:0)

答案存在于评论中

问题在于调用 刷新需要从当前线程

调用
this.Invoke((MethodInvoker)delegate
{
     this.m_LeftPictureBox.RefreshImage();
}