【问题标题】:.UpdateLayout() throwns an exception from RunWorkerCompleted method.UpdateLayout() 从 RunWorkerCompleted 方法抛出异常
【发布时间】:2015-03-05 14:52:45
【问题描述】:

我正在开发一个应用程序,我正在使用 BackgroundWorker 从 RunWorkerCompleted 方法将项目添加到列表视图。从 RunWorkerCompleted 方法中,我添加了 ListViewItems,我在其中设置了 .Content 和 .Background。

但是,在设置 .Background 属性并调用 ListView 类的 .UpdateLayout() 方法时,我遇到了一个异常:“不能使用属于与其父 Freezable 不同的线程的 DependencyObject。”。

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;
    }
}

任何建议将不胜感激:)

最好的问候。

【问题讨论】:

    标签: c# wpf listview exception backgroundworker


    【解决方案1】:

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

    您还没有展示完整的代码示例;特别是,从调用 Workload.Add() 方法的示例中不清楚。但鉴于错误消息,您似乎极有可能从BackgroundWorkerDoWork 事件处理程序调用它。当然,此处理程序在与执行RunWorkerCompleted 事件处理程序的 UI 线程不同的线程中运行,因此画笔对象是在与您要实际使用的线程不同的线程中创建的。

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

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

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

    【讨论】:

    • 感谢您的回复。您说得对,Workload.Add() 方法是从 BackgroundWorker 的 DoWork 事件处理程序中调用的。这对我有用:) - 我投票给你最好的答案!并感谢您关于不将工作负载结构称为与 Workload 类相同的提示 - 我知道它在未来可能会令人困惑;)
    猜你喜欢
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多