Sharat
Sharat

Reputation: 1

Thread not working properly

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

Answers (2)

Thorsten Dittmar
Thorsten Dittmar

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

Marc Gravell
Marc Gravell

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 Sleeps. It should not be a surprise that it hangs. Basically: split it into two steps:

  • processing - do this directly on the worker thread
  • UI - do this afterwards

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

Related Questions