简体   繁体   English

表单应用程序C#的无限while循环

[英]Infinite while loop with Form application C#

I need to run an infinite while loop when a form application starts. 当表单应用程序启动时,我需要运行一个无限的while循环。 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. 当我在构造函数中调用doProcess()时,它不显示表单。 I tried to run the while loop for 10 iterations. 我试图运行while循环10次迭代。 The form showed up only after all the iterations are finished. 仅在所有迭代完成后才显示该表单。 I don't understand why it is happening. 我不明白为什么会这样。

In short, you are blocking the UI Thread with this infinite loop. 简而言之,您将使用此无限循环来阻止UI线程。

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. 对于更新循环,while(true)可能会有点过多。 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. 我是否可以建议您潜在地使用计时器和/或利用“取消令牌”来急切取消请求,而这些请求花费了很长时间,以便在高性能情况下不以可能过时的结果更新UI。

Eg 例如

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();
    }
}

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() . 如果要从其他线程更新表单,则应使用: Form.Invoke()

For example: w is the form 例如: w是形式

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

It's happening because the ctor never exits and so the form cannot be shown - is this not obvious? 发生这种情况是因为ctor从未退出过,因此无法显示该表单-这不明显吗?

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). 不要在GUI事件处理程序(或ctor)中等待。

Can you not use forms.timer? 您不能使用forms.timer吗?

You are blocking the UI thread. 您正在阻止UI线程。 Therefore, the UI cannot be processed as long as doProcess runs. 因此,只要doProcess运行,就无法处理UI。

If you use .Net 4.5, you can use async waits: 如果使用.Net 4.5,则可以使用异步等待:

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. 较干净的解决方案是使用计时器,该计时器每1秒触发一次事件。 You can turn off the timer after 10 loops. 您可以在10个循环后关闭计时器。

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. 如果要在表单显示后执行此操作,请将代码放置在Form_Load事件中。 But you rather want to do it using background thread so you can use backgroundworker 但是您宁愿使用后台线程来执行此操作,以便可以使用backgroundworker

您可以将其放置在Initialize组件之后,或者找到表单的load事件,然后将代码粘贴到其中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM