【问题标题】:C# thread invoke freezing windowC#线程调用冻结窗口
【发布时间】:2015-01-04 12:51:58
【问题描述】:

这是冻结当前窗口的代码。如何使这个表格不冻结。

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)
    {

    }
}

【问题讨论】:

  • Invoke 在 UI 线程上运行一些代码,因此您实际上是在 UI 线程上运行整个无限循环,导致它被永久阻塞。跨度>

标签: c# multithreading asynchronous invoke


【解决方案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

【讨论】:

    【解决方案2】:

    如果您使用的是 .net 4.5,您的代码可以受益于使用 async-await。使用 await 您不必为您的 RunMe 方法启动单独的线程,它会释放您的 UI 线程来做其他工作,但 SynchronizationContext 被捕获,因此您不必使用 Invoke 来更新用户界面。有关其工作原理,请参阅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 线程中运行很短的时间。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 无法将 lambda 表达式转换为类型“System.Delegate”,因为它不是委托类型
      猜你喜欢
      • 2018-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-20
      • 1970-01-01
      相关资源
      最近更新 更多