C# 刷新PictureBox导致ArgumentException参数无效
我一辈子都搞不清楚这件事。我正在修改PictureBox指向的位图。基本上是有人在picturebox上拖动图像,图像会被更新,看起来就像是在picturebox上拖动一样。刷新picturebox时发生的情况是,我在Application.Run行上收到ArgumentException参数not valid错误,因此我花了一段时间才弄清楚到底是什么导致了这一情况,因为异常中没有更多信息 我创建了一个从picturebox派生的类,并重写了onpaint方法。它还有一个方法,RefreshImage,用于调用自身并刷新自身 如果不刷新picturebox,则不会出现此错误,但picturebox图像从未更新 我有一个主循环在后面运行,它更新了逻辑。逻辑是当拖动鼠标时,图像偏移量会更新 循环完成逻辑后,它会尝试刷新picturebox。这就是我发现当我注释掉刷新行时,我没有问题,但picturebox从未更新过。我在自定义picturebox类中添加了一个名为UpdateImage的方法,该方法调用自身,然后刷新 重写的onpaint方法从自定义循环线程获取逻辑,并根据后端循环线程更新的偏移量更新位图 主窗体是在主线程上创建的,picturebox也是在主线程上创建的,我已经检查过了 调用工作正常,后端线程在刷新picturebox时调用主线程 注释掉刷新行会使错误消失,但看不到picturebox更新 那么,对于更好的方法或者错误的解决方案,有什么建议吗 这是Derived picturebox类的一部分C# 刷新PictureBox导致ArgumentException参数无效,c#,winforms,thread-safety,C#,Winforms,Thread Safety,我一辈子都搞不清楚这件事。我正在修改PictureBox指向的位图。基本上是有人在picturebox上拖动图像,图像会被更新,看起来就像是在picturebox上拖动一样。刷新picturebox时发生的情况是,我在Application.Run行上收到ArgumentException参数not valid错误,因此我花了一段时间才弄清楚到底是什么导致了这一情况,因为异常中没有更多信息 我创建了一个从picturebox派生的类,并重写了onpaint方法。它还有一个方法,RefreshIm
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
}
}
还有一件事,为什么picturebox在主窗体刷新时不刷新?或者可能是主要形式不令人耳目一新?我确信如果是这样的话,我会看到光标没有被清除。我在自定义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 { }
}
}
答案存在于评论中 问题在于调用 刷新需要从当前线程调用
this.Invoke((MethodInvoker)delegate
{
this.m_LeftPictureBox.RefreshImage();
}
答案存在于评论中 问题在于调用 刷新需要从当前线程调用
this.Invoke((MethodInvoker)delegate
{
this.m_LeftPictureBox.RefreshImage();
}
如果将InvokeRequired检查放在更新方法中会发生什么情况?好问题,我最初尝试过,同样的问题,我只是将invoke检查移动到自定义类中,虽然是为了清理更新方法,但谢谢,请发布完整的stacktrace和可能更多的代码。您的问题提到应用程序上的ArgumentException参数无效错误。运行行。这不应该与多线程问题有关。对于stacktrace来说不太可能。它类似于[external code]->Program.Run()->[external code],因此如果我不在表单或picturebox上调用refresh,则重写的onpaint只在首次创建时调用一次。如果我从后台线程调用窗体上的刷新(调用它),我会得到相同的异常,但是在主线程上的实际刷新调用中,如果将invokererequired检查放在Update方法中会发生什么?好问题,我最初尝试过,同样的问题,我只是将调用检查移到了自定义类中,以清理更新方法,谢谢,请发布完整的stacktrace和可能更多的代码。您的问题提到应用程序上的ArgumentException参数无效错误。运行行。这不应该与多线程问题有关。对于stacktrace来说不太可能。它类似于[external code]->Program.Run()->[external code],因此如果我不在表单或picturebox上调用refresh,则重写的onpaint只在首次创建时调用一次。如果我从后台线程调用表单的刷新(调用它),我会得到相同的异常,但是在主线程的实际刷新调用上