【问题标题】:UI freezes when I add random numbers to a listbox on a separate thread当我将随机数添加到单独线程上的列表框时,UI 冻结
【发布时间】:2013-04-28 17:21:17
【问题描述】:

当我加载 windows 窗体时,使用新线程,我每秒向列表框添加一个随机数,当它达到 10 个数字时,我生成一组新的 10 个随机数。但是,目前,我遇到了 UI 线程的问题。随机数被添加到列表框中,但我无法控制表单。当我尝试与表单交互时,UI 冻结。我是否错误地使用了 MethodInvoker。任何建议将不胜感激。

public Form1()
    {
        InitializeComponent();
        Thread ranThread = new Thread(new ThreadStart(RandomList));
        ranThread.IsBackground = true;
        ranThread.Start();         
    }

public void RandomList()
    {
        stack = new Stack<int>(); 
        while (loop)
        {
            if (lbxStackRndNum.InvokeRequired)
            {
                lbxStackRndNum.Invoke(new MethodInvoker(delegate
                    {
                        Random rnd = new Random();

                        if (lbxStackRndNum.Items.Count == 10)
                        {
                            stack.Clear();
                            lbxStackRndNum.Items.Clear();
                        }

                        int rndVal = rnd.Next(1, 10000);
                        stack.Push(rndVal);
                        lbxStackRndNum.Items.Insert(0, rndVal);
                        Thread.Sleep(1000);
                    }));
            }
        }
    }

【问题讨论】:

    标签: c# multithreading winforms loops invoke


    【解决方案1】:

    您在调用的委托中调用 Thread.Sleep(1000),这意味着它将使 UI 线程进入睡眠状态,而不是 ranThread

    public void RandomList()
    {
        stack = new Stack<int>(); 
        while (loop)
        {
            if (lbxStackRndNum.InvokeRequired)
            {
                lbxStackRndNum.Invoke(new MethodInvoker(delegate
                    {
                        Random rnd = new Random();
    
                        if (lbxStackRndNum.Items.Count == 10)
                        {
                            stack.Clear();
                            lbxStackRndNum.Items.Clear();
                        }
    
                        int rndVal = rnd.Next(1, 10000);
                        stack.Push(rndVal);
                        lbxStackRndNum.Items.Insert(0, rndVal);
                    }));
                  Thread.Sleep(1000);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      由于实际工作是通过 Invoke() 和委托在主 UI 线程中完成的,并且所有线程真正在做的是通过 Sleep() 充当一秒计时器...为什么不添加将 ToolBox 中的常规 Timer() 设置为表单,将 Interval 设置为 1000,然后将代码放入 Tick() 事件中?

      【讨论】:

      • 通常情况下,我会这样做,但我正在学习线程、不安全代码和 ActiveX,并且我想尽可能多地将其纳入程序中以获得学习的好处。不过谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      • 2015-05-06
      • 2013-09-24
      相关资源
      最近更新 更多