private void DrawMap()
        {
            UpdateUI("正在绘图,请等待……");
            bmpDraw = new Bitmap(W, H);            Graphics g = Graphics.FromImage(bmpDraw);
            g.DrawImage(bmp, 0, 0);            Font f = new Font("宋体", 12, FontStyle.Bold);
            Brush b = new SolidBrush(Color.Black);
            g.DrawString(string.Format("{0,8:f1}毫米", ar[0]), f, b, 20, 250);
            ……………………
            f.Dispose(); b.Dispose();
            g.Dispose();            UpdateUI("绘图完毕!");            bmpDraw.Save(AppDomain.CurrentDomain.BaseDirectory + "result\\AR24.gif", System.Drawing.Imaging.ImageFormat.Gif);
            SaveImg();

        }        private void allWork()
        {
            DrawMap();
        }        // 切换回UI线程执行的入口
        // 现在没问题了,使用Invoke使得线程总是回到UI线程,所以我们可以放心大胆地调用控件的成员了
        private void UpdateUI(string str)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new dg1(UpdateUI),str);
            }
            else
            {
                toolStripStatusLabel1.Text = str;
            }
        }
        private void SaveImg()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new dg2(SaveImg));
            }
            else
            {
                pictureBox1.Image = bmpDraw;
                pictureBox1.Invalidate();
            }
        }        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            Thread myThread = new Thread(new ThreadStart(allWork));
            myThread.Start();        }
这样是没有问题的,但是如果稍微改变以下红色部分
        private void DrawMap()
        {
            UpdateUI("正在绘图,请等待……");
            bmpDraw = new Bitmap(W, H);            Graphics g = Graphics.FromImage(bmpDraw);
            g.DrawImage(bmp, 0, 0);            Font f = new Font("宋体", 12, FontStyle.Bold);
            Brush b = new SolidBrush(Color.Black);
            g.DrawString(string.Format("{0,8:f1}毫米", ar[0]), f, b, 20, 250);
            ……………………
            f.Dispose(); b.Dispose();
            g.Dispose();            UpdateUI("绘图完毕!");            SaveImg();
            bmpDraw.Save(AppDomain.CurrentDomain.BaseDirectory + "result\\AR24.gif", System.Drawing.Imaging.ImageFormat.Gif);

        }        private void allWork()
        {
            DrawMap();
        }        // 切换回UI线程执行的入口
        // 现在没问题了,使用Invoke使得线程总是回到UI线程,所以我们可以放心大胆地调用控件的成员了
        private void UpdateUI(string str)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new dg1(UpdateUI),str);
            }
            else
            {
                toolStripStatusLabel1.Text = str;
            }
        }
        private void SaveImg()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new dg2(SaveImg));
            }
            else
            {
                pictureBox1.Image = bmpDraw;
                pictureBox1.Invalidate();
            }
        }        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            Thread myThread = new Thread(new ThreadStart(allWork));
            myThread.Start();        }问题就出来了,编译通过,但是执行是提示:
未处理TargetInvocationException
InnerException:如果在使用GetHdc方法后使用Graphics对象,请调用ReleaseHdc方法

解决方案 »

  1.   

    甚至把以上代码改为
      UpdateUI("绘图完毕!");
      SaveImg();  private void SaveImg()
      {
      if (this.InvokeRequired)
      {
      this.BeginInvoke(new dg2(SaveImg));
      }
      else
      {
      bmpDraw.Save(AppDomain.CurrentDomain.BaseDirectory + "result\\AR24.gif", System.Drawing.Imaging.ImageFormat.Gif);
      pictureBox1.Image = bmpDraw;
      pictureBox1.Invalidate();
      }
      }
    也是出错
    但是改为这样的话又没问题:  UpdateUI("绘图完毕!");
      SaveImg();  private void SaveImg()
      {
      bmpDraw.Save(AppDomain.CurrentDomain.BaseDirectory + "result\\AR24.gif", System.Drawing.Imaging.ImageFormat.Gif);  
      if (this.InvokeRequired)
      {
      this.BeginInvoke(new dg2(SaveImg));
      }
      else
      {
      pictureBox1.Image = bmpDraw;
      pictureBox1.Invalidate();}
      }给我的感觉就是调用了SaveImg()后把线程送到UI线程上去了,然后就出这种奇怪的问题出来了(我水平太低,不知怎么描述了)
      

  2.   


      private void DrawMap()
      {
      UpdateUI("正在绘图,请等待……");
      bmpDraw = new Bitmap(W, H);  Graphics g = Graphics.FromImage(bmpDraw);
      g.DrawImage(bmp, 0, 0);  Font f = new Font("宋体", 12, FontStyle.Bold);
      Brush b = new SolidBrush(Color.Black);
      g.DrawString(string.Format("{0,8:f1}毫米", ar[0]), f, b, 20, 250);
      ……………………
      f.Dispose(); b.Dispose();
      g.Dispose();  UpdateUI("绘图完毕!");
    SaveImg();
      }  private void allWork()
      {
      DrawMap();
      }  // 切换回UI线程执行的入口
      // 现在没问题了,使用Invoke使得线程总是回到UI线程,所以我们可以放心大胆地调用控件的成员了
      private void UpdateUI(string str)
      {……  }
      private void SaveImg()
      {
      if (this.InvokeRequired)
      {
      this.BeginInvoke(new dg2(SaveImg));
      }
      else
      {

                    pictureBox1.Image = bmpDraw;
                    pictureBox1.Invalidate();
                    pictureBox1.Image.Save(AppDomain.CurrentDomain.BaseDirectory + "result\\AR24.gif", System.Drawing.Imaging.ImageFormat.Gif);

      }
      }
    这样也没问题
    如果修改一下,结果又出错
      private void SaveImg()
      {
      if (this.InvokeRequired)
      {
      this.BeginInvoke(new dg2(SaveImg));
      }
      else
      {

                    pictureBox1.Image.Save(AppDomain.CurrentDomain.BaseDirectory + "result\\AR24.gif", System.Drawing.Imaging.ImageFormat.Gif);
                    pictureBox1.Image = bmpDraw;
                    pictureBox1.Invalidate();

      }
      }
      

  3.   

    不要在多线程中直接调用界面控件.而应该使用委托,如BeginInvoke
      

  4.   

    已经用了委托,如BeginInvoke
    现在的问题就是委托这一步的执行顺序导致的问题