Reputation: 1
I made a program on stenography which is working properly but NOT RESPONDING when large text files are used. I need to implement threads to it. It tried with the below code but still it gave me the same problem. Don't know actually where i made mistake. also i need to add a progress bar, but don't know where to add the code.
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;
}
Thank You.
Upvotes: 0
Views: 1639
Reputation: 56697
The thing is: You're running your stuff within a thread, but the thread code is run in the context of the UI thread because you invoke it using this.BeginInvoke
. Actually, only parts that update the UI need to be invoked using this.Invoke
.
So while you think your multi-threaded, you actually are not.
Please also use this.Invoke
, not this.BeginInvoke
, as for BeginInvoke
you also need to call EndInvoke
at some point, otherwise you leak memory/resources.
How to solve it? My suggestion:
Prepare the data for your thread within the UI thread. That is: Getting text from text boxes, maybe images from picture boxes, etc. Pass this to the thread, maybe as an object of a State
class in the state
parameter of ParameterizedThreadStart
.
Then, have the thread do nothing related to UI! No message boxes, no updating of picture boxes, nothing. Update everything when the thread ends.
If that works, you may incorporate status updates, which are then called in the form of
this.Invoke((Action)delegate()
{
progressBar.Value = ...;
}
or
this.Invoke((Action)delegate()
{
pictureBox.Image = ...;
}
Upvotes: 1
Reputation: 1062780
It looks like you are doing all the thinking on the UI thread via the BeginInvoke
. You aren't actually doing any work of consequence on the worker thread. In fact, the only thing you are doing on the worker thread is counting to 100 with some Sleep
s. It should not be a surprise that it hangs. Basically: split it into two steps:
Occasionally, you might mix the two - i.e. update the UI via BeginInvoke
or Invoke
in batches during the thinking. Not every row / item / iteration - just occasionally (every 1000 rows, for example)
Upvotes: 0