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

时间:2015-01-07 16:33:04

标签: c# wpf listview exception backgroundworker

我正在开发应用,我使用BackgroundWorker从RunWorkerCompleted方法向listview添加项目。从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);
        }

    }

这是Workload类:

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

任何建议都将受到赞赏:)

最好的问候。

1 个答案:

答案 0 :(得分:0)

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

您尚未展示完整的代码示例;特别是,从示例中调用您的Workload.Add()方法并不清楚。但是鉴于错误消息,您似乎很可能是从BackgroundWorker的{​​{1}}事件处理程序中调用它。当然,这个处理程序在与执行DoWork事件处理程序的UI线程不同的线程中运行,因此刷子对象是在与您想要实际使用它的线程不同的线程中创建的。

基本上:框架禁止这样做。

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

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