启动线程后,UI冻结

时间:2019-04-20 21:58:18

标签: c# .net multithreading visual-studio

我有一个问题,我一直在努力寻找,我没有幸运地在这里找到正确的答案。我的问题是当我使用 BackgroundWorker()调用函数 dosomeWork()时),则该UI会完全冻结。 我已经添加了From1的控件来进行委派,以避免更新线程错误。

        public void dosomeWork()
        {
.
.
.
           for (int i = 0; i <= listline.Count; i += range)
                {
                    status.Text = "test if i can change label name without freezing";
                    isChecked(listline.GetRange(i, range));

                }

            }

        }

代理功能

        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Delegate del = new DELEGATE(dosomeWork);
            this.Invoke(del);
            Delegate del2 = new TheMethod(isChecked);
            this.Invoke(del2);

        }

BackgroundWorker功能

        private void button1_Click(object sender, EventArgs e)
        {
            worker.DoWork += worker_DoWork;
            worker.RunWorkerAsync();
        }

通常它应该正常工作。请告知。

1 个答案:

答案 0 :(得分:0)

您要一个单独的线程来更改GUI线程中的某些内容(即使它是在GUI线程上启动的,但仍然是单独的),并且不允许跨线程操作GUI线程项由于您遇到的原因。这就是为什么它冻结。


您需要针对所有与GUI相关的变量和控件将操作调用回GUI线程。这是我在VM中使用的方法:

public static void SafeOperationToGuiThread(Action operation)
{
    System.Windows.Application.Current?.Dispatcher?.Invoke(operation);
}

您将这样使用:

        public void dosomeWork()
        {

           for (int i = 0; i <= listline.Count; i += range)
                {

                MyVM.SafeOperationToGuiThread( () => { 
                    status.Text = "test if i can change label name without freezing";
                    isChecked(listline.GetRange(i, range));
                      }

                }

            }

        }

当我更改属性而不是控件时,我也遇到了这个问题,并且发现控件和属性不能不受跨线程操作的影响。这是我的文章:

C# WPF: Linq Fails in BackgroundWorker DoWork


备用选项

请注意,如果一个人提供了一个 run workercompleted 委托,然后又不必调用回GUI,那么它也可以通过后台工作来更新gui。我在博客上提供了一个示例:

C# WPF: Threading, Control Updating, Status Bar and Cancel Operations Example All In One