简体   繁体   English

C#帮助需要的错误

[英]c# help needed error

Cross-thread operation not valid: Control 'ocrTB' accessed from a thread other than the thread it was created on. 跨线程操作无效:控制“ ocrTB”是从创建该线程的线程之外的其他线程访问的。

This is the error i have. 这是我的错误。 And below is my coding. 下面是我的编码。

#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

Any solution for this? 有什么解决办法吗?

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

You are executing this delegate asynchronously in a different thread - are you sure that's what you want? 您正在不同的线程中异步执行此委托-确定要这样做吗? That being the case you can use Control.Invoke() to update a UI control from another thread (the one your ProcessImages2 method is executed under) : 在这种情况下,您可以使用Control.Invoke()从另一个线程(执行ProcessImages2方法的一个线程Control.Invoke()更新UI控件:

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

In general it would be easier to use a background worker to process your data and update it in the Completed event handler. 通常,使用后台工作程序来处理您的数据并在Completed事件处理程序中更新它会更容易。

You cannot modify the UI in any thread other than the UI thread, ProcessImages2 in this example attempts to do this, you need to use Dispatcher.Invoke or just run ProcessImages2 in the same thread (ie don't do processImagesDelegate.BeginInvoke . 您不能在UI线程以外的任何线程中修改UI,此示例中的ProcessImages2尝试执行此操作,您需要使用Dispatcher.Invoke或仅在同一线程中运行ProcessImages2 (即,不要执行processImagesDelegate.BeginInvoke

Also, posting a big chunk of code can be good, but try to give details on which line is throwing the error! 另外,发布大量代码可能会很好,但是请尝试提供有关哪一行引发错误的详细信息!

You need to marshal back to the other thread when trying to access controls on the UI from a new thread.. You can use Control.Invoke like such: 尝试从新线程访问UI上的控件时,需要编组回到另一个线程。您可以使用Control.Invoke,如下所示:

 someControl.Invoke((MethodInvoker)delegate
        {

            someControl.DoSomething();

        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM