Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 509
  • Last Modified:

My Form is not responding

Hi,
When I run my code, and click a button, the msgs are dispalyed in the rich textbox.
When I tried to move the scroll bar on the richtextbox while the process was still running, the whole form became "not responding."
What should I do to use my scroll bar to see all the displays while the process is still running?

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Update();
            this.richTextBox1.Clear();          
           
            for (int i = 0; i < 3; i++)
           {
                AddHi(i);
                Thread.Sleep(10000);
                AddBye(i);
            }
               
           
            this.button1.Enabled = true;
        }    
        public delegate void GreetingDelegate(string str);
        public void AddGreeting(string str)
        {
            if (this.richTextBox1.InvokeRequired)
            {
                this.richTextBox1.Invoke(new GreetingDelegate(AddGreeting), str);
                return;
            }
            else
            {
                this.richTextBox1.AppendText(str);
                this.richTextBox1.Refresh();
            }
        }        
        public void AddHi(int i)
        {
            try
            {
                AddGreeting("Hi " + i.ToString() + "\n");

            }
            catch (Exception e)
            {
                e.Message.ToString();
            }
        }

        public void AddBye(int i)
        {
            try
            {
                AddGreeting("Bye " + i.ToString() + "\n");

            }
            catch (Exception e)
            {
                e.Message.ToString();
            }
        }        
    }
}
0
IzzyTwinkly
Asked:
IzzyTwinkly
  • 6
  • 2
  • 2
  • +4
4 Solutions
 
IzzyTwinklyAuthor Commented:
My form still gets 'not responding' with Application.DoEvent().  Is put that in the for loop from my code.
0
 
SameerJagdaleCommented:
try removing
Thread.Sleep(10000);

from your code.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
IzzyTwinklyAuthor Commented:
Thread.Sleep(10000) should be there.  that simulates a method that takes some time to process.  
0
 
saraganiCommented:
Let me explain you a little about threads.

The GUI runs on the main thread of the application. Once you do an infinite loop or sleep (in your cause for 10 seconds), the main thread become locked and the GUI doesn't redraw itself.

This is why your form is not responding.

In my opinion Any action that takes 500 Milliseconds  should be performed on another thread.


Your form should start a new thread that will do the long process job, while in the meanwhile the parts in the form that need to be disabled get disabled.

When the thread finished doing what it supposed to do then it re-enables what it needs in the form and do whatever action in needs to do in the form, all of that while considering thread safety and preventing cross-thread access to the GUI
(You will need to use delegates to do this.Invoke when this.InvokeRequired is true)
0
 
anyoneisCommented:
saragani has it. But since I had coded this change for you, here it is:
 
David

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
 
namespace RichTextDelay
{
    public partial class Form1 : Form
    {
        Thread backgroundThread = null;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            this.button1.Enabled = false;
            this.richTextBox1.Update();
            this.richTextBox1.Clear();
            backgroundThread = new Thread(delegate() { DoStuff(); });
            backgroundThread.Start();
        }
        private void DoStuff()
        {
            for (int i = 0; i < 3; i++)
            {
                AddHi(i);
                Thread.Sleep(10000);
                AddBye(i);
            }
            this.Invoke((MethodInvoker) delegate { this.button1.Enabled = true; });
        }
        
        public delegate void GreetingDelegate(string str);
        public void AddGreeting(string str)
        {
            if (this.richTextBox1.InvokeRequired)
            {
                this.richTextBox1.Invoke(new GreetingDelegate(AddGreeting), str);
                return;
            }
            else
            {
                this.richTextBox1.AppendText(str);
                this.richTextBox1.Refresh();
            }
        }        
        public void AddHi(int i)
        {
            try
            {
                AddGreeting("Hi " + i.ToString() + "\n");
 
            }
            catch (Exception e)
            {
                e.Message.ToString();
            }
        }
 
        public void AddBye(int i)
        {
            try
            {
                AddGreeting("Bye " + i.ToString() + "\n");
 
            }
            catch (Exception e)
            {
                e.Message.ToString();
            }
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (backgroundThread != null)
            {
                backgroundThread.Abort();
                backgroundThread = null;
            }
        }        
    }
}

Open in new window

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
If you want to "simulate" long "work" then try something like this:

    Delay(10); // delay for ten seconds

The method:
        private void Delay(int DelayInSeconds)
        {
            TimeSpan ts;
            DateTime targetTime = DateTime.Now.AddSeconds(DelayInSeconds);
            do
            {
                ts = targetTime.Subtract(DateTime.Now);
                Application.DoEvents(); // keep app responsive
                System.Threading.Thread.Sleep(50); // reduce CPU usage
            }
            while (ts.TotalSeconds > 0);
        }

Open in new window

0
 
IzzyTwinklyAuthor Commented:
I see your point saragani.  I guess you mean I need to use the method(in this case, Thread.Sleep(10000)) with a new thread between AddHi(i) and AddBye(i).  I guess I also need to make AddBye(i) wait until Thread.Sleep(10000) is all done.
Could you show me some example or code?  I checked msdn, but still confusing how to apply cross-thread solution in my case.
0
 
IzzyTwinklyAuthor Commented:
oh  I have some codes now.  never mind my previous comment.  Thanks!
0
 
CuteBugCommented:
You can modify your code like this
public partial class Form1 : Form
{
    bool wait = true;
 
    public Form1()
    {
        InitializeComponent();
    }
 
    private void button1_Click(object sender, EventArgs e)
    {
        this.button1.Enabled = false;
 
        this.richTextBox1.Update();
        this.richTextBox1.Clear();
 
        for (int i = 0; i < 3; i++)
        {
            AddHi(i);
 
            Thread waitThread = new Thread(new ThreadStart(WaitMethod));
            waitThread.Start();
            while (wait)
            {
                Application.DoEvents();
            }
 
            AddBye(i);
        }
        
        this.button1.Enabled = true;
    }
 
    public void WaitMethod()
    {
        Thread.Sleep(10000);
        wait = false;
    }
 
    public delegate void GreetingDelegate(string str);
    
    public void AddGreeting(string str)
    {
        if (this.richTextBox1.InvokeRequired)
        {
            this.richTextBox1.Invoke(new GreetingDelegate(AddGreeting), str);
            return;
        }
        else
        {
            this.richTextBox1.AppendText(str);
            this.richTextBox1.Refresh();
        }
    }
 
    public void AddHi(int i)
    {
        try
        {
            AddGreeting("Hi " + i.ToString() + "\n");
 
        }
        catch (Exception e)
        {
            e.Message.ToString();
        }
    }
 
    public void AddBye(int i)
    {
        try
        {
            AddGreeting("Bye " + i.ToString() + "\n");
 
        }
        catch (Exception e)
        {
            e.Message.ToString();
        }
    }
}

Open in new window

0
 
IzzyTwinklyAuthor Commented:
Wow..it's really cool. Thanks!

I have a qucik question from your code, anyoneis.
Could you explain 'this.Invoke((MethodInvoker) delegate { this.button1.Enabled = true; });' little bit?  I guess that you are make the button enable, but I want to know more detailed steps with Invoke, MethodInvoker, etc...
0
 
saraganiCommented:
He is using something called Anonymous Methods. It is a cool thing that Vb.Net doesn't support.

This is a good example of updating the GUI from another thread:
http://www.codeproject.com/KB/cs/ModelViewPresenterWithDI.aspx

This is where I first saw the cool usage of anonymous methods (before that I had to write my own delegates, and lots of them, for doing this.invoke).

Just search for UpdateUI in that article.
0
 
anyoneisCommented:
It is just a shorthand for the same thing you did with GreetingDelegate - it reduces all of the delegate declarations and little event functions that you have to write.
I like this article: http://www.yoda.arachsys.com/csharp/csharp2/delegates.html#anonymous.methods
where he gives this example:
using System;
delegate void SomeAction();
class Test
{
     static void Main(string[] args)
     {
          SomeAction instance = delegate { Console.WriteLine(args[0]); }; instance();
     }
}  
The reason the above works is becuase the compiler knows what kind of delegate it needs (SomeAction.). In my cvase, it did not, so I had to tell it with a cast. I hjave seen others use "Action" as the delegate type in this situation.
            this.Invoke((MethodInvoker) delegate { this.button1.Enabled = true; });.
 David
0
 
IzzyTwinklyAuthor Commented:
Thank you so much.  
I might need to open another question about cross threaded operation. =)
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 6
  • 2
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now