线程工作不正常
本文关键字:不正常 工作 线程 | 更新日期: 2023-09-27 17:58:22
我制作了一个关于速记的程序,该程序工作正常,但在使用大型文本文件时没有响应。我需要实现它的线程。它尝试使用下面的代码,但仍然给了我同样的问题。实际上不知道我在哪里犯了错误。我还需要添加一个进度条,但不知道在哪里添加代码。
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;
}
谢谢。
问题是:您在线程中运行您的东西,但线程代码是在UI线程的上下文中运行的,因为您使用this.BeginInvoke
调用它。实际上,只有更新UI的部分才需要使用this.Invoke
调用。
因此,当你认为是你的多线程时,你实际上不是。
也请使用this.Invoke
,而不是this.BeginInvoke
,因为对于BeginInvoke
,您还需要在某个时刻调用EndInvoke
,否则会泄漏内存/资源。
如何解决?我的建议:
在UI线程中为线程准备数据。也就是说:从文本框中获取文本,可能从图片框中获取图像,等等。将其传递给线程,可能作为ParameterizedThreadStart
的state
参数中State
类的对象。
然后,让线程不做任何与UI相关的事情!没有消息框,没有图片框更新,什么都没有。线程结束时更新所有内容。
如果有效,您可以合并状态更新,然后以的形式调用
this.Invoke((Action)delegate()
{
progressBar.Value = ...;
}
或
this.Invoke((Action)delegate()
{
pictureBox.Image = ...;
}
看起来您正在通过BeginInvoke
对UI线程进行所有思考。你实际上并没有在worker线程上做任何重要的工作。事实上,您在工作线程上所做的唯一一件事就是用一些Sleep
s计数到100。它挂起并不奇怪。基本上:分为两个步骤:
- 处理-直接在工作线程上执行
- UI-之后执行此操作
有时,您可能会将两者混合使用,即在思考过程中通过BeginInvoke
或Invoke
批量更新UI。不是每一行/项目/迭代-只是偶尔(例如,每1000行)