跨线程操作无效:控制'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
对此有何解决方案?
答案 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();
});