急求:如何捕获“存储空间不足”的异常

songyan 2010-06-11 12:14:56
用C#写的WinForm程序,因为很多处要用到图像放大的功能,就写了一个由TrackBar和PictureBox构成的UserControl。PictureBox的SizeMode属性设为StretchImage,然后在TrackBar的事件里:
private void trackBar_Zoom_ValueChanged(object sender, EventArgs e)
{
try
{
float _coefficient = (100 + trackBar_Zoom.Value) / 100F;

picBox_Scale.Size = new Size(Convert.ToInt32(picBox_Source.Width * _coefficient), Convert.ToInt32(picBox_Source.Height * _coefficient)); //改变PictureBox的大小
label_Scale.Text = (100 + trackBar_Zoom.Value).ToString()+ "%"; //显示放大倍数
}
catch (Exception E)
{
if (E is System.ComponentModel.Win32Exception)
{
System.ComponentModel.Win32Exception exception = E as System.ComponentModel.Win32Exception;
if (exception.ErrorCode == -2147467259)
{
trackBar_Zoom.Enabled = false;
picBox_Scale.Image.Dispose();
picBox_Scale.Dispose();
GC.Collect();

...... //重新new 一个picBox_Scale以及初始化设置,程序较长,省略

MessageBox.Show(E.Message, "出错", MessageBoxButtons.OK, MessageBoxIcon.Warning);
trackBar_Zoom.Enabled = true;
}
}
else
{
MessageBox.Show(E.Message, "出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

当放大倍数到了接近20倍时(测试图片是1440×900,电脑2G内存,客户要求最大放大倍数是32倍)就发生异常了,而且发现上面这个try catch根本不能捕获异常,异常是在ValueChanged事件执行完后才抛出的。在 Application的ThreadException事件里能捕获这个异常,但是程序里用了很多个这种UserControl,因而无法在ThreadException确定是哪个出错了并进行恢复。请问有没有什么办法能在UserControl里就捕获这个异常?

附出错信息:
未处理 System.ComponentModel.Win32Exception
Message="存储空间不足,无法处理此命令。"
Source="System.Drawing"
ErrorCode=-2147467259
NativeErrorCode=8
StackTrace:
在 System.Drawing.BufferedGraphicsContext.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits)
在 System.Drawing.BufferedGraphicsContext.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height)
在 System.Drawing.BufferedGraphicsContext.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
在 System.Drawing.BufferedGraphicsContext.AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
在 System.Drawing.BufferedGraphicsContext.Allocate(IntPtr targetDC, Rectangle targetRectangle)
在 System.Windows.Forms.Control.WmPaint(Message& m)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
在 System.Windows.Forms.Application.Run(Form mainForm)
在 Microsoft.VisualStudio.Tools.UserControlTestContainer.Main(String[] args)
...全文
778 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
songyan 2010-06-12
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 pclion 的回复:]
放大32倍,图像像素数就是放大32*32=1024倍!
一个1K*1K的图像放大32倍,内存量是1K*1K*1024*3=3GB!(RGB图像像素是3字节)
要能支持放大32倍,只能对图像作局部截取,再放大.
[/Quote]
-------------------------------------------------------------------------
这个算法比较复杂,和客户沟通后,客户同意在OutOfMemoery时做个警告提示即可,程序不能退出或崩溃。现在就是截获不到这个异常。
songyan 2010-06-12
  • 打赏
  • 举报
回复
to wuyq11:
用你的方法,发现一个很奇怪的问题:
1、在VS2008的用户控件测试容器里调试,UnhandledException事件会触发。好象UnhandledException事件不会阻止异常抛出吧?运行结果是,UnhandledException事件执行完后,异常还是抛出,程序中止。

2、直接用主程序调试(就是用户控件调试时选“启动外部程序”),发现在用户控件里加的UnhandledException事件完全没有执行,只执行了Application.ThreadException。我把Application.ThreadException注释掉,结果是出来了系统的那个异常窗口,用户控件里加的UnhandledException事件还是没有执行。是不是要用什么方法去设置?
songyan 2010-06-11
  • 打赏
  • 举报
回复
to zzx509:

Application.ThreadException 的参数sender是Thread类型,我不知道怎么去确定是哪个UserControl的PicturBox出错(程序里用了很多个这种UserControl),如果不把出错的PicturBox Dispose掉并重新new一个,程序会不停地报OutOfMemoryException。

我写过一个测试程序,只放一个Usercontrol,出错后只要在Application.ThreadException里把出错的PicturBox Dispose掉,GC.Collect(),然后重新new一个,就可以恢复正常。

也谢谢上面几位!
wuyq11 2010-06-11
  • 打赏
  • 举报
回复
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptions);
private void UnhandledExceptions(object sender, UnhandledExceptionEventArgs args)
{ }
zzx509 2010-06-11
  • 打赏
  • 举报
回复
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is OutOfMemoryException)
{
}
}

void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
if (e.Exception is OutOfMemoryException)
{
}
}
足球中国 2010-06-11
  • 打赏
  • 举报
回复
main()
{
try
{

}
catch()
{

}
}在这里可能能捕获可能不是你想要的。

你最好能计算出多少就会出错。自己来throw错误,自己捕获。
zhubo006 2010-06-11
  • 打赏
  • 举报
回复
帮顶了
xk1126 2010-06-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wuyq11 的回复:]
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptions);
private void UnhandledExceptions(object sender, ……
[/Quote]
up
pclion 2010-06-11
  • 打赏
  • 举报
回复
放大32倍,图像像素数就是放大32*32=1024倍!
一个1K*1K的图像放大32倍,内存量是1K*1K*1024*3=3GB!(RGB图像像素是3字节)
要能支持放大32倍,只能对图像作局部截取,再放大.
zzx509 2010-06-11
  • 打赏
  • 举报
回复
绘制前将当前UserControl放单例对象的属性中。
public class Singleton
{
static Singleton pub = new Singleton();
public Singleton()
{

}
private UserControl control;

public UserControl Control
{
get { return control; }
set { control = value; }
}
public static Singleton Instance
{
get { return pub; }
}
}

出异常后Singleton.Instance.Control.Dispose();

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧