Graphics drawBoard;
        protected override void OnPaint(PaintEventArgs e)
        {
            drawBoard = e.Graphics;
            base.OnPaint(e);            Thread thread = new Thread(new ThreadStart(this.DrawTest));
            thread.Start();
            
        }
        private void FormMain_Load(object sender, EventArgs e)
        {
            MessageBox.Show(this, "开始绘制?");
        }        private void DrawTest()
        {
            Thread.Sleep(3000);
            Pen pen = new Pen(Color.Red, 4);            drawBoard.TranslateTransform(100, 100);            drawBoard.DrawRectangle(pen, 10, 10, 30, 20);            drawBoard.Dispose();
        }
      这个是我的一个小测试,因为我另外有个地方要用GDI+画很多点,所以就用了多线程。
      之前不用多线程没问题,但就是加入多线程后老是抛出参数无效异常。
      drawBoard.TranslateTransform(100, 100);   异常就是在这里抛出。
      就算我把上面这个语句注释掉,但下面那个画矩形的还是会抛出同样的异常。
      貌似GDI+和多线程就是一对冤家!!!
      请大家求解!!!

解决方案 »

  1.   

    Graphics drawBoard;
    protected override void OnPaint(PaintEventArgs e)
    {
    //这样尝试一下,因为e离开堆栈就会没有引用指向e,执行Dispose,主动的
    //把内部的Graphics对象也释放掉了,所以你可以考虑创建一个新的
    drawBoard = this.CreateGraphics();
    base.OnPaint(e); Thread thread = new Thread(new ThreadStart(this.DrawTest));
    thread.Start();

    }
    private void FormMain_Load(object sender, EventArgs e)
    {
    MessageBox.Show(this, "开始绘制?");
    }private void DrawTest()
    {
    Thread.Sleep(3000);
    Pen pen = new Pen(Color.Red, 4);
    drawBoard.TranslateTransform(100, 100);
    drawBoard.DrawRectangle(pen, 10, 10, 30, 20);
    drawBoard.Dispose();
    pen.Dispose();//注意释放
    }
      

  2.   


    LS。。果然高。。解决了。。我这里说一下对你那句话的理解。。是不是因为在子线程里面没有引用指向e啊。。但如果这样的话应该是抛出drawBoard的没有设置对象实例的异常,那你说的执行Dispose是在什么时候执行的呢。有没有相关技术文章呢?谢谢!!!
      

  3.   

    其实也只是猜测。因为垃圾回收大概原理了解,在这个地方,我猜测是这样过程:
    e作为形参,在函数执行完成后,就会随着堆栈的释放而被释放掉,但此时释放的是引用。在随后的某个时候,垃圾回收(一共3次逐级执行),第一次的回收中,对没有引用指向的对象,判断如果实现了IDispose接口,则调用Dispose,此时可能调用e实际对象的Dispose。
    而这是猜测,因为你的drawBoard指向e.Graphics,那么按道理说不属于被释放的要求,因为还有引用指向对象,但是不排除在e这个对象的Dispose方法中,系统写了e.Graphics.Dispose。如果真是我假设的这样,那你使用的时候,就会出点问题。但因为是垃圾回收分3次执行,可能e.Graphics此时只是无效,但并不是null。所以不是NullRefranceException。以上理论性的东西纯属猜测了。没实际的测试支持。
      

  4.   

    简单说,是这个意思。函数结束->e形参出栈->垃圾回收->e.Dispose()->e.Graphics.Dispose()
    此时drawBoard无效,但不是空引用。
      

  5.   

    GDI+ is but one of many Microsoft libraries that cannot handle concurrency.