C#thread调用冻结窗口

时间:2015-01-04 12:51:59

标签: c# multithreading asynchronous invoke

这是代码冻结当前窗口。如何使这种形式不冻结。

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 个答案:

答案 0 :(得分:1)

正如其他人所说,你正在使用UI线程执行无限循环,你应该使用Timer控件,它是为你正在做的事情而构建的。

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

答案 1 :(得分:1)

如果您使用.net 4.5,则使用async-await可以使您的代码受益。使用await您不必为RunMe方法启动单独的线程,它将释放您的UI线程以执行其他工作,但会捕获SynchronizationContext以便您不会必须使用Invoke来更新UI。有关其工作原理,请参阅this blog

我认为您应该能够像这样重写代码:

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循环,但该方法只会唤醒更新标签并在UI线程中运行很短的时间。

答案 2 :(得分:0)

您应该仅调用调用来更新标签,如下所示:

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