c# - 在工作线程中创建对象并绑定(bind)到它们

标签 c# wpf exception binding multithreading

我在 C#/WPF/.NET 4.0 中遇到跨线程操作问题。

情况:

当用户单击一个按钮然后绑定(bind)到树时,我必须创建一个对象树。由于创建耗时较长(子对象递归实例化),我使用了Thread/BackgroundWorker/Task来防止UI卡顿。

问题:

当绑定(bind)到对象树时,我得到一个 XamlParserException(必须在与 DependencyObject 相同的线程上创建 DependencySource)。

我明白问题所在,但如何解决?我无法在 UI 线程上创建对象树,因为这会卡住 UI。但我也无法在另一个线程上创建对象树,因为那样我就无法绑定(bind)到它。

有没有办法将对象“编码”到 UI 线程?

事件处理程序代码(在 UI 线程上执行)

    private void OnDiff(object sender, RoutedEventArgs e)
    {

        string path1 = this.Path1.Text;
        string path2 = this.Path2.Text;

        // Some simple UI updates.
        this.ProgressWindow.SetText(string.Format(
            "Comparing {0} with {1}...",
            path1, path2));

        this.IsEnabled = false;
        this.ProgressWindow.Show();
        this.ProgressWindow.Focus();

        // The object tree to be created.
        Comparison comparison = null;

        Task.Factory.StartNew(() =>
        {

            // May take a few seconds...
            comparison = new Comparison(path1, path2);

        }).ContinueWith(x =>
        {


            // Again some simple UI updates.
            this.ProgressWindow.SetText("Updating user interface...");
            this.DiffView.Items.Clear();
            this.Output.Items.Clear();

            foreach (Comparison diffItem in comparison.Items)
            {
                this.DiffView.Items.Add(diffItem);

                this.AddOutput(diffItem);
            }

            this.Output.Visibility = Visibility.Visible;

            this.IsEnabled = true;
            this.ProgressWindow.Hide();

        }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());

    }

示例绑定(bind)

            <DataGrid.Columns>
                <DataGridTemplateColumn CellTemplate="{StaticResource DataGridIconCellTemplate}"/>
                <DataGridTextColumn Header="Status" Binding="{Binding Path=ItemStatus}"/>
                <DataGridTextColumn Header="Type"   Binding="{Binding Path=ItemType}"/>
                <DataGridTextColumn Header="Path"   Binding="{Binding Path=RelativePath}"
                                    Width="*"/>
            </DataGrid.Columns>

您好, 多米尼克

最佳答案

您可以在工作线程上创建图标,但在 UI 线程上使用它之前需要先卡住它:

            var icon = Imaging.CreateBitmapSourceFromHIcon(
              sysicon.Handle,
              System.Windows.Int32Rect.Empty,
              System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            icon.Freeze();
            Dispatcher.Invoke(new Action(() => this.Icon = icon));

关于c# - 在工作线程中创建对象并绑定(bind)到它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5649166/

相关文章:

c# - VSTO 可安装或 exe

c# - 如何在附加行为中使用单例计时器来更改 ListView 项目的背景颜色?

wpf - 有什么方法可以使 WPF 菜单中的分隔符更窄?

c++ - LWG2349 会有什么影响?

c# - 加载 pcap 文件

c# - 为什么核心类型只实现了部分接口(interface)?

c# - 使用递归获取整数中的位数

c# - 如何使用不同文件夹的本地/用户控制

c# - 无效的变体崩溃

python - getattr 的最大递归深度错误