.UpdateLayout() 从 RunWorkerCompleted 方法抛出异常

本文关键字:方法 抛出异常 RunWorkerCompleted UpdateLayout | 更新日期: 2023-09-27 18:36:41

我正在开发一个应用程序,其中我正在使用BackgroundWorker从RunWorkerComplete方法将项目添加到列表视图中。从 RunWorkerCompleted 方法中,我正在添加列表视图项,我正在设置 .内容和 .背景。

但是,在设置 .后台属性并调用 .ListView 类的 UpdateLayout() 方法,我得到一个异常:"无法使用与其父级 Freezable 属于不同线程的依赖对象。

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        try
        {
            if (e.Cancelled == true)
            {
                System.Windows.MessageBox.Show("Something..cancelled");
            }
            else if (e.Error != null)
            {
                System.Windows.MessageBox.Show("Something..error " + e.Error.Message);
            }
            else
            {
                workLoad_listView.Items.Clear();
                workLoad_listView.Height = 23;
                foreach (Workload.workload element in Workload.Get())
                {
                    System.Windows.Controls.ListViewItem item = new System.Windows.Controls.ListViewItem();
                    item.Content = (string)element.name;
                    item.Background = element.brush; // if I outcomment this line, no exception is thrown!
                    workLoad_listView.Items.Add(item);
                }
                workLoad_listView.UpdateLayout(); //exception is thrown here!
                while (FindVisualChild<ScrollViewer>(workLoad_listView).ComputedVerticalScrollBarVisibility == Visibility.Visible)
                {
                    workLoad_listView.Height += 1;
                    workLoad_listView.UpdateLayout();
                }
            }
        }
        catch (Exception ex)
        {
            System.Windows.MessageBox.Show(string.Format("An exception was thrown!'n{0}", ex), "Exception caught", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

这是工作负载类:

public static class Workload
{
    public struct workload
    {
        public string name;
        public System.Windows.Media.SolidColorBrush brush;
    }
    private static List<workload> workload_list = new List<workload>();
    public static void Add(string name, int colorNumber)
    {
        workload tmp_workload = new workload();
        tmp_workload.name = name;
        System.Drawing.Color color = System.Drawing.ColorTranslator.FromWin32(colorNumber);
        tmp_workload.brush = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromArgb(255, (byte)color.R, (byte)color.G, (byte)color.B));
        workload_list.Add(tmp_workload);
    }
    public static void Clear()
    {
        workload_list.Clear();
    }
    public static List<workload> Get()
    {
        return workload_list;
    }
}

任何建议将不胜感激:)

此致敬意。

.UpdateLayout() 从 RunWorkerCompleted 方法抛出异常

System.Windows.Media.SolidColorBrush 类型派生自 DependencyObjectDependencyObject 类型具有线程亲和力;也就是说,它只能在创建它的线程中使用。

您尚未显示完整的代码示例;特别是,从示例中不清楚调用Workload.Add()方法的位置。但是考虑到错误消息,您很可能是从BackgroundWorkerDoWork事件处理程序调用此消息的。当然,此处理程序在与执行 RunWorkerCompleted 事件处理程序的 UI 线程不同的线程中运行,因此 brush 对象是在与您希望实际使用它的线程不同的线程中创建的。

基本上:这是框架禁止的。

同样,如果没有完整的代码示例,很难确定最佳解决方案是什么。但是,根据此处显示的代码,在我看来,您应该将 brush 的System.Windows.Media.Color值存储在 workload 结构中而不是 Brush 值中,然后在 RunWorkerCompleted 事件处理程序中创建Brush本身。

我还建议更改类型名称,以便您不会同时拥有Workload类和workload结构。有两个类型名称仅在第一个字母的情况下不同,这可能会让其他可能想要阅读代码的人(或者在你忘记如何实现它几个月后对你自己)感到非常困惑。