我正在使用backgroundworker并获取:InvalidOperationException:跨线程操作无效 - 我应该如何处理它?

时间:2015-02-04 03:03:53

标签: c# .net multithreading winforms backgroundworker

考虑:

private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
    Bitmap newbmp = new Bitmap(512, 512);
    IEnumerable<Point> CommonList = null;
    StreamWriter w = new StreamWriter(@"c:\diff\diff.txt");
    pixelscoordinatesinrectangle = new List<Point>();
    pixelscoordinatesinrectangle = pointsAffected.ToList();
    DrawIt = false;
    for (int i = 0; i < trackBar1FileInfo.Length; i++)
    {
        DrawIt = true;
        this.BeginInvoke(new MethodInvoker(delegate
        {
            trackBar1.Value = i;

                    LoadPictureAt(trackBar1.Value, sender);
                    pictureBox1.Load(trackBar1FileInfo[i].FullName);

            ConvertedBmp = ConvertTo24(trackBar1FileInfo[trackBar1.Value].FullName);
            ConvertedBmp.Save(ConvertedBmpDir + "\\ConvertedBmp.bmp");
            mymem = ToStream(ConvertedBmp, ImageFormat.Bmp);
        }));
        Button1Code();
        pictureBox1.Refresh();
        newpixelscoordinates = new List<Point>();
        newpixelscoordinates = pointsAffected.ToList();
        CommonList = pixelscoordinatesinrectangle.Intersect(newpixelscoordinates);
        foreach (Point s in CommonList)
        {
            w.WriteLine("The following points are the same" + s);
            newbmp.SetPixel(s.X, s.Y, Color.Red);
        }
    }
    w.Close();
    using (Graphics G = Graphics.FromImage(newbmp))
    {
        G.DrawRectangle(pen, rect);
    }
    newbmp.Save(@"c:\newbmp\newbmp.bmp", ImageFormat.Bmp);
    newbmp.Dispose();
}

异常消息:

  

跨线程操作无效:控制&#39; pictureBox1&#39;从创建它的线程以外的线程访问。

我尝试使用this.BeginInvoke(new MethodInvoker(delegate

即使现在在BeginInvoke之后使用代码时,它也显示异常,所以我也需要在其他代码上使用BeginInvoke。

使用BeginInvoke是一个好方法吗?或者我应该以其他方式解决它,如果是这样的话?

1 个答案:

答案 0 :(得分:2)

在Windows GUI编程中:

  1. 将耗时的任务移至单独的线程以保持UI响应,您选择使用BackgroundWorker,这是一个不错的选择。
  2. 您无法从后台线程(Cross-thread operation not valid例外)访问UI元素,因此您需要调用BeginInvoke来访问Picturebox。
  3. 请记住,BeginInvoke调用的代码实际上是在UI线程上运行的。因此,如果您将所有代码放在BeginInvoke 中的DoWork中,那就与不使用Backgroundworker相同 - 实际上它更糟糕,因为创建一个新线程并将调用封送到UI线程有很大的性能开销。

    因此,只有在必要时才应调用BeginInvoke - 当代码需要访问UI元素时,其余代码不应包含在BeginInvoke内。