.UpdateLayout() 从 RunWorkerCompleted 方法中抛出异常
.UpdateLayout() throwns an exception from RunWorkerCompleted method
我正在开发一个应用程序,我在其中使用 BackgroundWorker 从 RunWorkerCompleted 方法向列表视图添加项目。从 RunWorkerCompleted 方法中,我添加了 ListViewItems,我在其中设置了 .Content 和 .Background。
然而,当设置 .Background 属性并调用 ListView 类的 .UpdateLayout() 方法时,出现异常:"Cannot use a DependencyObject that belongs to a different thread than its parent 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;
}
}
如有任何建议,我们将不胜感激:)
此致。
System.Windows.Media.SolidColorBrush
类型派生自 DependencyObject
。 DependencyObject
类型具有线程亲和性;也就是说,它只能在创建它的线程中使用。
您还没有展示完整的代码示例;特别是,从调用 Workload.Add()
方法的示例中不清楚。但是鉴于错误消息,您似乎极有可能是从 BackgroundWorker
的 DoWork
事件处理程序调用它。当然,此处理程序与执行 RunWorkerCompleted
事件处理程序的 UI 线程在不同的线程中运行,因此画笔对象是在与您想要创建的线程不同的线程中创建的实际使用它。
基本上:这是框架禁止的。
同样,如果没有完整的代码示例,则很难确定最佳解决方案是什么。但是,根据此处显示的代码,在我看来您应该将画笔的 System.Windows.Media.Color
值存储在 workload
结构中而不是 Brush
值,然后创建Brush
本身在 RunWorkerCompleted
事件处理程序中。
我还建议更改类型名称,这样您就不会同时拥有 Workload
class 和 workload
结构。拥有两个仅在第一个字母的情况下不同的类型名称可能会让其他可能想要阅读代码的人感到困惑(或者对你自己来说,几个月后你已经忘记了你是如何实现它的)。
我正在开发一个应用程序,我在其中使用 BackgroundWorker 从 RunWorkerCompleted 方法向列表视图添加项目。从 RunWorkerCompleted 方法中,我添加了 ListViewItems,我在其中设置了 .Content 和 .Background。
然而,当设置 .Background 属性并调用 ListView 类的 .UpdateLayout() 方法时,出现异常:"Cannot use a DependencyObject that belongs to a different thread than its parent 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;
}
}
如有任何建议,我们将不胜感激:)
此致。
System.Windows.Media.SolidColorBrush
类型派生自 DependencyObject
。 DependencyObject
类型具有线程亲和性;也就是说,它只能在创建它的线程中使用。
您还没有展示完整的代码示例;特别是,从调用 Workload.Add()
方法的示例中不清楚。但是鉴于错误消息,您似乎极有可能是从 BackgroundWorker
的 DoWork
事件处理程序调用它。当然,此处理程序与执行 RunWorkerCompleted
事件处理程序的 UI 线程在不同的线程中运行,因此画笔对象是在与您想要创建的线程不同的线程中创建的实际使用它。
基本上:这是框架禁止的。
同样,如果没有完整的代码示例,则很难确定最佳解决方案是什么。但是,根据此处显示的代码,在我看来您应该将画笔的 System.Windows.Media.Color
值存储在 workload
结构中而不是 Brush
值,然后创建Brush
本身在 RunWorkerCompleted
事件处理程序中。
我还建议更改类型名称,这样您就不会同时拥有 Workload
class 和 workload
结构。拥有两个仅在第一个字母的情况下不同的类型名称可能会让其他可能想要阅读代码的人感到困惑(或者对你自己来说,几个月后你已经忘记了你是如何实现它的)。