1

I need to run an infinite while loop when a form application starts. A form starts like this:

public Form1()
{
        InitializeComponent();
}

Now I want to run another function which will have an infinite loop inside with one second sleep time:

public void doProcess(){

    while(true){
         Thread.Sleep(1000);
         // other task
    }
}

How can I do this? When I call doProcess() in the constructor, it does not show the form. I tried to run the while loop for 10 iterations. The form showed up only after all the iterations are finished. I don't understand why it is happening.

3
  • Where do you invoke the doProcess method? Before or after the InitializeComponent? And have you tried the form_load event? Commented Jun 17, 2013 at 8:02
  • 1
    P.s, use pascal casing "DoProcess" Commented Jun 17, 2013 at 8:04
  • 1
    I did not understand, what exactly you want to do.. I mean if you are running the infinite loop which has Thread.Sleep(1000) (for 1 sec), so it will not show the form as it is infinitely taking break and if you are putting it for 10 iterations then obviously it will show after 10 iterations. So can you please be little clear about the question. :) Commented Jun 17, 2013 at 8:05

6 Answers 6

5

In short, you are blocking the UI Thread with this infinite loop.

Run it async:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        BeginWork();
    }

    private async void BeginWork()
    {
        while (true)
        {
            // Since we asynchronously wait, the UI thread is not blocked by the file download.
            var result = await DoWork(formTextField.Text);

            // Since we resume on the UI context, we can directly access UI elements.
            formTextField.Text = result;
        }
    }

    private async Task<string> DoWork(object text)
    {
        // Do actual work
        await Task.Delay(1000);
        // Return Actual Result
        return DateTime.Now.Ticks.ToString();
    }
}

A while(true) can be a bit excessive for an update loop. May I recommend that you potentially use a Timer, and/or leverage Cancellation Tokens to eagerly cancel requests which have taken too long as to not update UI with potentially stale results in high performance scenarios.

E.g.

public partial class Form1 : Form
{
    private readonly Timer _sampleTimer;

    public Form1()
    {
        InitializeComponent();

        _sampleTimer = new Timer
            {
                Interval = 500 // 0.5 Seconds
            };
        _sampleTimer.Tick += DoWorkAndUpdateUIAsync;
    }

    private async void DoWorkAndUpdateUIAsync(object sender, EventArgs e)
    {
        // Since we asynchronously wait, the UI thread is not blocked by "the work".
        var result = await DoWorkAsync();

        // Since we resume on the UI context, we can directly access UI elements.
        resultTextField.Text = result;
    }

    private async Task<string> DoWorkAsync()
    {
        await Task.Delay(1000); // Do actual work sampling usb async (not blocking ui)
        return DateTime.Now.Ticks.ToString(); // Sample Result
    }

    private void startButton_Click(object sender, EventArgs e)
    {
        _sampleTimer.Start();
    }

    private void stopButton_Click(object sender, EventArgs e)
    {
        _sampleTimer.Stop();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

4

You can start a new thread like this:

new Thread(() => 
{
    while (true)
    {
        Thread.Sleep(1000);

        //other tasks
    }
}).Start();

Although I suggest you read up on threading before you do. If you want to update the form from a different thread you should use: Form.Invoke().

For example: w is the form

 w.Invoke((MethodInvoker) delegate
 {
     w.Width += 100;
 });

Comments

2

It's happening because the ctor never exits and so the form cannot be shown - is this not obvious?

If you want to run a forever/sleep loop line this, you must thread it off.

Do not wait in GUI event handlers, (or ctors).

Can you not use forms.timer?

Comments

1

You are blocking the UI thread. Therefore, the UI cannot be processed as long as doProcess runs.

If you use .Net 4.5, you can use async waits:

public async void doProcess(){
    while(true){
         await Task.Delay(1000);
         // other task
    }
}

The cleaner solution would be to use a timer that fires an event every 1 second. You can turn off the timer after 10 loops.

1 Comment

You mean await Task.Delay(1000);
0

You didn't exit the constructor so the form won't show. If you want to do it after form shows place your code in Form_Load event. But you rather want to do it using background thread so you can use backgroundworker

Comments

0

You could place it after the Initialize component, or find the load event of the form and paste your code in there

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.