C# 使用dispatcher.invoke时程序冻结

C# 使用dispatcher.invoke时程序冻结,c#,wpf,multithreading,C#,Wpf,Multithreading,我在数据库中有多个类别(类别、子类别)。 我想把这些子类别归入普通类别。 这是我的方法: private void LoadCategories() { connection = new MySqlConnection(conf.connection_string); MySqlCommand cmd = new MySqlCommand(); cmd.Connection = connection; cmd.CommandText = "SELECT * FRO

我在数据库中有多个类别(类别、子类别)。 我想把这些子类别归入普通类别。 这是我的方法:

private void LoadCategories()
{
    connection = new MySqlConnection(conf.connection_string);
    MySqlCommand cmd = new MySqlCommand();
    cmd.Connection = connection;
    cmd.CommandText = "SELECT * FROM auftrags_typ_category";

    if (this.OpenConnection() == true)
    {
        try
        {
            MySqlDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                int categoryID = (int)reader["id"];
                #region Create Expander
                Expander cat_expander = new Expander();
                cat_expander.ExpandDirection = ExpandDirection.Right;
                TextBlock cat_name = new TextBlock();
                cat_name.Text = reader["name"].ToString();
                cat_name.RenderTransformOrigin = new Point(0.5, 0.5);
                cat_name.LayoutTransform = new RotateTransform() { Angle = 90 };
                cat_expander.Header = cat_name;

                Thread t = new Thread(() => LoadUnderCategories(categoryID));
                t.SetApartmentState(ApartmentState.STA);
                t.Start();
                t.Join();

                Border border = new Border();
                border.Width = 1;
                border.VerticalAlignment = VerticalAlignment.Stretch;
                border.SnapsToDevicePixels = true;
                border.Background = (Brush)FindResource("MaterialDesignDivider");

                cat_expander.Content = serviceList;
                serviceListSP.Children.Add(cat_expander);
                serviceListSP.Children.Add(border);

                serviceList.Items.Clear();
                #endregion
            }
        }
        catch (MySqlException ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
}    
我尝试使用线程暂停代码以调用LoadUnderCategories:

private void LoadUnderCategories(int categoryID)
{
    connection = new MySqlConnection(conf.connection_string);
    MySqlCommand cmd = new MySqlCommand();
    cmd.Connection = connection;
    cmd.CommandText = "SELECT * FROM auftrags_typ_childcategory WHERE category = @categoryID";
    cmd.Parameters.AddWithValue("@categoryID", categoryID);

    if (this.OpenConnection() == true)
    {
        try
        {
            MySqlDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                TreeViewItem child_category = new TreeViewItem();
                child_category.Header = reader["name"].ToString();
                Application.Current.Dispatcher.Invoke((Action)(() =>
                {
                    serviceList.Items.Add(child_category);
                }));

            }
        }
        catch (MySqlException ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
}
我声明了
treeviewservicelist=newtreeview()全局


但是程序冻结了。如果我使用
Dispatcher.Invoke
,当程序冻结时如何访问全局
serviceList

@fetype在注释中写到使用
BeginInvoke
而不是
Invoke
。 这起作用了。程序不再冻结。谢谢

我在评论中声明为答案的另一个问题也通过以下方式解决:

TreeView serviceList = new TreeView();
Thread t = new Thread( () => LoadUnderCategories(categoryID, serviceList) );


希望这是正确的方法。

尝试将整个循环放在dispatcher中,而不仅仅是add函数,您在循环中调用dispatcher,这可能是问题的一部分。或者,尝试使用BeginInvoke而不是Invoke(这是同步的)。可能在某一点上,您的工作线程将同时等待UI线程和UI线程。它仍然会冻结。编辑:使用BeginInvoke它可以工作。但它不会停下来。我有三个子类。2的id为1,最后一个子类别的id为2。但所有子类别都会转到id为4的最后一个类别。所以我想。t、 Join不起作用。因为子类别将添加到最后一个类别。
private void LoadUnderCategories(int categoryID, TreeView serviceList)