c#help需要的错误

时间:2011-04-09 16:59:12

标签: c# multithreading

跨线程操作无效:控制'ocrTB'从其创建的线程以外的线程访问。

这是我的错误。以下是我的编码。

#region OCR(Tab5_Component)
    //When user is selecting, RegionSelect = true
    private bool RegionSelect = false;
    private int x0, x1, y0, y1;
    private Bitmap bmpImage;

    private void loadImageBT_Click(object sender, EventArgs e)
    {
        try
        {
            OpenFileDialog open = new OpenFileDialog();
            open.InitialDirectory = @"C:\Users\Shen\Desktop";

            open.Filter = "Image Files(*.jpg; *.jpeg)|*.jpg; *.jpeg";

            if (open.ShowDialog() == DialogResult.OK)
            {
                singleFileInfo = new FileInfo(open.FileName);
                string dirName = System.IO.Path.GetDirectoryName(open.FileName);
                loadTB.Text = open.FileName;
                pictureBox1.Image = new Bitmap(open.FileName);
                bmpImage = new Bitmap(pictureBox1.Image);
            }

        }
        catch (Exception)
        {

            throw new ApplicationException("Failed loading image");

        }
    }

    //User image selection Start Point
    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        RegionSelect = true;

        //Save the start point.
        x0 = e.X;
        y0 = e.Y;
    }

    //User select image progress
    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        //Do nothing it we're not selecting an area.
        if (!RegionSelect) return;

        //Save the new point.
        x1 = e.X;
        y1 = e.Y;

        //Make a Bitmap to display the selection rectangle.
        Bitmap bm = new Bitmap(bmpImage);

        //Draw the rectangle in the image.
        using (Graphics g = Graphics.FromImage(bm))
        {
            g.DrawRectangle(Pens.Red, Math.Min(x0, x1), Math.Min(y0, y1), Math.Abs(x1 - x0), Math.Abs(y1 - y0));
        }

        //Temporary display the image.
        pictureBox1.Image = bm;
    }

    //Image Selection End Point
    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        // Do nothing it we're not selecting an area.
        if (!RegionSelect) return;
        RegionSelect = false;

        //Display the original image.
        pictureBox1.Image = bmpImage;

        // Copy the selected part of the image.
        int wid = Math.Abs(x0 - x1);
        int hgt = Math.Abs(y0 - y1);
        if ((wid < 1) || (hgt < 1)) return;

        Bitmap area = new Bitmap(wid, hgt);
        using (Graphics g = Graphics.FromImage(area))
        {
            Rectangle source_rectangle = new Rectangle(Math.Min(x0, x1), Math.Min(y0, y1), wid, hgt);
            Rectangle dest_rectangle = new Rectangle(0, 0, wid, hgt);
            g.DrawImage(bmpImage, dest_rectangle, source_rectangle, GraphicsUnit.Pixel);
        }

        // Display the result.
        pictureBox3.Image = area;
        pictureBox3.Image.Save(@"C:\Users\Shen\Desktop\LenzOCR\TempFolder\tempPic.jpg");

    }

    /*private void loadFolderBT_Click(object sender, EventArgs e)
    {
        folderBrowserDialog.ShowDialog();
        folderLocation.Text = folderBrowserDialog.SelectedPath;
    }*/

    private void ScanBT_Click(object sender, EventArgs e)
    {
        var folder = @"C:\Users\Shen\Desktop\LenzOCR\LenzOCR\WindowsFormsApplication1\ImageFile";

        DirectoryInfo directoryInfo;
        FileInfo[] files;
        directoryInfo = new DirectoryInfo(folder);
        files = directoryInfo.GetFiles("*.jpg", SearchOption.AllDirectories);

        exit = false;


        var processImagesDelegate = new ProcessImagesDelegate(ProcessImages2);
        processImagesDelegate.BeginInvoke(files, null, null);

        System.IO.File.Delete(@"C:\Users\Shen\Desktop\LenzOCR\TempFolder\tempPic.jpg");
    }

    private void ProcessImages2(FileInfo[] files)
    {
        var comparableImages = new List<ComparableImage>();

        //Invoke(setMaximumDelegate, new object[] { workingProgressBar, files.Length });

        var index = 0x0;

        var operationStartTime = DateTime.Now;

        foreach (var file in files)
        {
            if (exit)
            {
                return;
            }

            var comparableImage = new ComparableImage(file);
            comparableImages.Add(comparableImage);
            index++;
            //Invoke(updateOperationStatusDelegate, new object[] { "Processed images", workingLabel, workingProgressBar, index, operationStartTime });
        }

        //Invoke(setMaximumDelegate, new object[] { workingProgressBar, comparableImages.Count });

        index = 0;

        similarityImagesSorted = new List<SimilarityImages>();

        operationStartTime = DateTime.Now;

        var fileImage = new ComparableImage(singleFileInfo);

        for (var i = 0; i < comparableImages.Count; i++)
        {
            if (exit)
                return;

            var destination = comparableImages[i];
            var similarity = fileImage.CalculateSimilarity(destination);
            var sim = new SimilarityImages(fileImage, destination, similarity);
            similarityImagesSorted.Add(sim);
            index++;

            //Invoke(updateOperationStatusDelegate, new object[] { "Compared images", workingLabel, workingProgressBar, index, operationStartTime });
        }

        similarityImagesSorted.Sort();
        similarityImagesSorted.Reverse();
        similarityImages = new BindingList<SimilarityImages>(similarityImagesSorted);

        var buttons =
            new List<Button>
                {
                    ScanBT
                };

        if (similarityImages[0].Similarity > 85)
        {
            //MessageBox.Show("Similarity(%) : " + similarityImages[0].Similarity.ToString(), "Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //MessageBox.Show("Similarity(%) : " + similarityImages[0].Destination.ToString(), "Result", MessageBoxButtons.OK, MessageBoxIcon.Information); 
            //MessageBox.Show("Similarity(%) : " + similarityImages[0].Source.ToString(), "Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
            con = new System.Data.SqlClient.SqlConnection();
            con.ConnectionString = "Data Source=SHEN-PC\\SQLEXPRESS;Initial Catalog=CharacterImage;Integrated Security=True";
            con.Open();

            String getFile = "SELECT ImageName, Character FROM CharacterImage WHERE ImageName='" + similarityImages[0].Destination + "'";
            SqlCommand cmd2 = new SqlCommand(getFile, con);
            SqlDataReader rd2 = cmd2.ExecuteReader();

            while (rd2.Read())
            {
                ocrTB.Text = rd2["Character"].ToString(); // <<<<<< error occur here
            }
            con.Close();
        }
        else
        {
            MessageBox.Show("No character found!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

    }
    #endregion

对此有何解决方案?

3 个答案:

答案 0 :(得分:1)

var processImagesDelegate = new ProcessImagesDelegate(ProcessImages2);
processImagesDelegate.BeginInvoke(files, null, null);

您正在另一个线程中异步执行此委托 - 您确定这是您想要的吗?在这种情况下,您可以使用Control.Invoke()从另一个线程(您的ProcessImages2方法执行的那个线程)更新UI控件:

string text = rd2["Character"].ToString();
Action updateText = () => ocrTB.Text = text;
ocrTB.Invoke(updateText);

通常,使用后台工作程序处理数据并在Completed事件处理程序中更新它会更容易。

答案 1 :(得分:0)

您无法在UI线程以外的任何线程中修改UI,本例中的ProcessImages2尝试执行此操作,您需要使用Dispatcher.Invoke或仅运行ProcessImages2线程(即不要processImagesDelegate.BeginInvoke

此外,发布大量代码可能会很好,但请尝试详细说明哪一行引发了错误!

答案 2 :(得分:0)

当您尝试从新线程访问UI上的控件时,您需要编组回到其他线程。您可以像这样使用Control.Invoke:

 someControl.Invoke((MethodInvoker)delegate
        {

            someControl.DoSomething();

        });