用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)

解决方案 »

  1.   

    main()
    {
    try
    {}
    catch()
    {}
    }在这里可能能捕获可能不是你想要的。你最好能计算出多少就会出错。自己来throw错误,自己捕获。
      

  2.   

    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)
    {
    }
    }
      

  3.   

    AppDomain currentDomain = AppDomain.CurrentDomain;   
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptions);   
      private void UnhandledExceptions(object sender, UnhandledExceptionEventArgs args)   
      { }
      

  4.   

    to zzx509:Application.ThreadException 的参数sender是Thread类型,我不知道怎么去确定是哪个UserControl的PicturBox出错(程序里用了很多个这种UserControl),如果不把出错的PicturBox Dispose掉并重新new一个,程序会不停地报OutOfMemoryException。我写过一个测试程序,只放一个Usercontrol,出错后只要在Application.ThreadException里把出错的PicturBox Dispose掉,GC.Collect(),然后重新new一个,就可以恢复正常。也谢谢上面几位!
      

  5.   

    绘制前将当前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();
      

  6.   

    放大32倍,图像像素数就是放大32*32=1024倍!
    一个1K*1K的图像放大32倍,内存量是1K*1K*1024*3=3GB!(RGB图像像素是3字节)
    要能支持放大32倍,只能对图像作局部截取,再放大.
      

  7.   

    to wuyq11:
    用你的方法,发现一个很奇怪的问题:
    1、在VS2008的用户控件测试容器里调试,UnhandledException事件会触发。好象UnhandledException事件不会阻止异常抛出吧?运行结果是,UnhandledException事件执行完后,异常还是抛出,程序中止。2、直接用主程序调试(就是用户控件调试时选“启动外部程序”),发现在用户控件里加的UnhandledException事件完全没有执行,只执行了Application.ThreadException。我把Application.ThreadException注释掉,结果是出来了系统的那个异常窗口,用户控件里加的UnhandledException事件还是没有执行。是不是要用什么方法去设置?
      

  8.   

    -------------------------------------------------------------------------
    这个算法比较复杂,和客户沟通后,客户同意在OutOfMemoery时做个警告提示即可,程序不能退出或崩溃。现在就是截获不到这个异常。