C# поток вызывает заморозить окно

Это код заморозки текущего окна. Как сделать не замораживая эту форму.

public partial class Form1 : Form
{
    Thread t;

    int s = 0;
    public Form1()
    {
        InitializeComponent();

        label2.Text = "Push the Button";
        button1.Text = "Push me!";
        button1.Click += new EventHandler(button1_Click);

        this.Controls.Add(label2);
        this.Controls.Add(button1);
    }

    void button1_Click(object sender, EventArgs e)
    {
        t = new Thread(new ThreadStart(RunMe));
        t.Start();
    }

    private void RunMe()
    {
            if (!InvokeRequired)
            {
                while(true)
                {
                    label2.Text = s.ToString();
                    s++;
                    Task.Delay(10000).Wait(10000);
                }
            }
            else
            {
                Invoke(new ThreadStart(RunMe));
            }
    }


    private void Form1_Load(object sender, EventArgs e)
    {

    }
}

3 ответа

Ваш код может извлечь выгоду из использования async-await если вы используете.net 4.5. С помощью await вам не нужно начинать отдельную тему для вашего RunMe метод, он освободит ваш поток пользовательского интерфейса для выполнения другой работы, но SynchronizationContext захватывается, так что вам не нужно использовать Invoke обновить пользовательский интерфейс. Как это работает, смотрите в этом блоге.

Я думаю, что вы должны быть в состоянии переписать свой код следующим образом:

async void button1_Click(object sender, EventArgs e)
{ 
    // kicks off the RunMe method and returns
    await RunMe();
}

private Task RunMe()
{
    while(true)
    {
        label2.Text = s.ToString();
        s++;
        await Task.Delay(10000);
    }    
}

Несмотря на бесконечность while loop метод активируется только для обновления метки и работает в течение очень короткого времени в потоке пользовательского интерфейса.

Как уже говорили другие, вы используете поток пользовательского интерфейса для выполнения бесконечного цикла, вы должны использовать Timer контроль, он был построен именно для того, что вы делаете.

https://social.msdn.microsoft.com/Forums/windows/en-US/43daf8b2-67ad-4938-98f7-cae3eaa5e63f/how-to-use-timer-control-in-c?forum=winforms

Вы должны вызывать invoke только для обновления метки следующим образом:

while(true)
{
    if (!InvokeRequired)
    {
        label2.Text = s.ToString();
    }
    else
    {
        Invoke(new Action(()=>{label2.Text = s.ToString();}));
    }
    s++;
    Task.Delay(10000).Wait(10000);
}
Другие вопросы по тегам