我制作了一个关于速记的程序,该程序工作正常,但在使用大型文本文件时无法响应。我需要为它实现线程。 它尝试使用下面的代码,但它仍然给了我同样的问题。 实际上我不知道我犯了什么错误。 我还需要添加一个进度条,但不知道在哪里添加代码。
private void button3_Click(object sender, EventArgs e)
{
Thread myThread = new System.Threading.Thread(delegate()
{
RUN();
for (int n = 0; n < 100; n++)
{
Thread.Sleep(50);
progressBar1.BeginInvoke(new Action(() => progressBar1.Value = n));
}
});
myThread.Start();
}
private void RUN()
{
if (this.InvokeRequired)
{
this.BeginInvoke((MethodInvoker)delegate()
{
int ascii;
String xor;
String text = textBox1.Text;
if (textBox1.Text != "")
{
Bitmap bitmap = (Bitmap)pictureBox1.Image;
Bitmap bmp = (Bitmap)pictureBox1.Image;
//richTextBox1.Text = "\n";
byte[] asciiBytes = Encoding.ASCII.GetBytes(textBox1.Text);// Convert the string into a byte[].
int x0 = 0, y0 = 0;
// Error checking, to see if text can fit in image
int imageSize = bitmap.Width * bitmap.Height;
if (imageSize - x0 * bitmap.Width - y0 < 8 * textBox1.Text.Length)
{
MessageBox.Show("Too Large");
}
for (int t = 0; t < textBox1.Text.Length; t++)
{
ascii = asciiBytes[t];
xor = program.binlength(Convert.ToString(ascii ^ 254, 2));
//richTextBox1.Text = richTextBox1.Text + xor + "\n";
for (int i = 0; i < 8; i++)
{
// Check if y0 has exceeded image width
// so to wrap around to the new row
if (y0 == bitmap.Width)
{
x0++;
y0 = 0;
}
hide(bmp, bitmap, y0, x0, i,xor);
// x0, y0 are now the current pixel coordinates
//
// EMBED MESSAGE HERE
//
y0++; // Move to the next pixel for the next bit
}
}
MessageBox.Show("" + (text.Length * 8));
}
else
MessageBox.Show("Text???");
});
}
}
private void hide(Bitmap bmp, Bitmap bitmap,int y0,int x0,int i,string xor)
{
Color colorpixel,newcolor;
String pixR;
colorpixel = bitmap.GetPixel(y0, x0);
pixR = program.binlength(Convert.ToString(Convert.ToInt32(colorpixel.R), 2));
newcolor = Color.FromArgb(Convert.ToByte(program.converttopixcel(xor, pixR, i), 2), colorpixel.G, colorpixel.B);
bmp.SetPixel(y0, x0, newcolor);
pictureBox2.Image = bmp;
}
谢谢。
答案 0 :(得分:1)
问题是:你在一个线程中运行你的东西,但线程代码在UI线程的上下文中运行,因为你使用this.BeginInvoke
调用它。实际上,只需要使用this.Invoke
调用更新UI的部分。
因此,当您认为您的多线程时,实际上并非如此。
请同时使用this.Invoke
,而不是this.BeginInvoke
,因为BeginInvoke
您还需要在某个时候调用EndInvoke
,否则会泄漏内存/资源。
如何解决?我的建议是:
在UI线程中准备线程的数据。即:从文本框中获取文本,也可以从图片框中获取图像等。将其传递给线程,可以作为State
state
类中ParameterizedThreadStart
类的对象。
然后,让线程与UI相关的 nothing !没有消息框,没有更新图片框,没有。线程结束时更新所有内容。
如果可行,您可以合并状态更新,然后以
的形式调用this.Invoke((Action)delegate()
{
progressBar.Value = ...;
}
或
this.Invoke((Action)delegate()
{
pictureBox.Image = ...;
}
答案 1 :(得分:0)
看起来你正在通过BeginInvoke
对UI线程进行所有思考。你实际上并没有在工作线程上做任何有意义的工作。事实上,你在工作线程上做的唯一事情就是用一些Sleep
来计算到100。它挂起来应该不足为奇。基本上:将其分为两个步骤:
有时,您可能会将两者混合使用 - 即在思考过程中分批通过BeginInvoke
或Invoke
更新UI。不是每一行/项目/迭代 - 只是偶尔(例如,每1000行)