运行此代码时出现错误:
tabControl1.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { tabControl1.Items.Add(tbItem); }));
tabcontrol1被硬编码到xaml中,TAB项/s是在运行时构建的。我得到一个错误:
TargetInvocationException抛出了未处理的异常调用的目标。
我很想听听大家对这个问题的看法。由于
更新内部异常:
{"调用线程无法访问这个对象是因为一个不同的线程拥有它。"}
完整方法代码:
TabItem tbItem = new TabItem();
tbItem.Header = worker;
Grid grid = new Grid();
ListBox listBox = new ListBox();
listBox.HorizontalAlignment = HorizontalAlignment.Stretch;
listBox.VerticalAlignment = VerticalAlignment.Stretch;
listBox.ItemsSource = datasource.Where(i => i.Category == worker);
grid.Children.Add(listBox);
tbItem.Content = grid;
tabControl1.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { tabControl1.Items.Add(tbItem); }));
方法是这样调用的:
Thread newThread = new Thread(myMethod);
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
另一个更新如此:
tabControl1.Dispatcher.Invoke(DispatcherPriority.Normal,
(Action)(() =>
{
TabItem tbItem = new TabItem();
tbItem.Header = worker;
//Grid & ListBox(within tab item)
Grid grid = new Grid();
ListBox listBox = new ListBox();
listBox.HorizontalAlignment = HorizontalAlignment.Stretch;
listBox.VerticalAlignment = VerticalAlignment.Stretch;
listBox.ItemsSource = datasource.Where(i => i.Category == worker);
grid.Children.Add(listBox);
tbItem.Content = grid;
tabControl1.Items.Add(tbItem);
}));
正如你所看到的,你的tbItem是在不同的线程上创建的,即使它试图将它分派回TAbControl的主gui线程。
为什么不提取出需要更长时间的部分(您正在使用线程),一旦您得到结果,继续创建tbItem并将其添加到GUI线程中的TabControl
的例子:
tabControl.Dispatcher.Invoke calls below function with dataSoruce result it gets
List<string> result = null;
tabControl.Dispatcher.Invoke((Action<IEnumerable<string>>)ProcessResult, result);
public void ProcessResult(IEnumerable<string> datasource)
{
//this is where you do creating TabItem and assigning data source to it and adding to TabControl.
}
未编译,请检查语法
检查InnerException
属性,找出原因。TargetInvocationException
只是wpf运行时的一个包装器。你的lambda可能会抛出异常,但如果没有实际的异常,你无法判断。
编辑
您在不同的线程中创建TabItem
,因此GUI线程无法访问它,即使您使用调度程序进行实际添加。正如您已经发布的上一个代码片段一样,您必须在GUI线程中创建TabItem
。只在不同的线程中进行计算,一旦结果返回,在GUI线程中实际创建TabItem
(如果需要通过Dispatcher
)。
问题是你在一个单独的线程上创建你的ui元素。这是不允许的。
你可以在后台线程(调用datasource.Where(i => i.Category == worker);
)上进行处理,但不幸的是,每个UI元素都需要完全在主用户界面线程上构造和使用。
在你的例子中,这意味着在Dispatcher调用的UI线程中构造ListBox和Grid。
我建议将其重写为:
// Load the data on the background...
var data = datasource.Where(i => i.Category == worker);
// Do all work on the UI thread
tabControl1.Dispatcher.Invoke(DispatcherPriority.Normal,
(Action)(() =>
{
TabItem tbItem = new TabItem();
tbItem.Header = worker;
//Grid & ListBox(within tab item)
Grid grid = new Grid();
ListBox listBox = new ListBox();
listBox.HorizontalAlignment = HorizontalAlignment.Stretch;
listBox.VerticalAlignment = VerticalAlignment.Stretch;
listBox.ItemsSource = data;
grid.Children.Add(listBox);
tbItem.Content = grid;
tabControl1.Items.Add(tbItem);
}));