WPF-使用Backgroundworker加载Visio文件

/免责声明,这是我第一次使用WPF和多线程,所以如果我犯了一些大错误,请多多包涵/

所以我有一个带有Tab控件的应用程序。在其中一个选项卡中,我打算通过通常的Windows窗体宿主+ Visio Viewer activeX控件等加载visio文件。唯一的问题是,当我在文档中加载时,UI冻结了20秒(因为我正在加载相当大的文件)。如我所读,这是因为我的应用程序在一个简单的线程上运行。因此,我试图实现一个后台工作程序,以在后台线程运行时保持UI处于活动状态。

实例化UserControl时,我将其添加到选项卡(Initialpath是visio文件的文件路径):

        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += Worker_DoWork;
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        worker.RunWorkerAsync(initialpath);


        private void Worker_DoWork(object sender,DoWorkEventArgs e)
        {
        DiagramView UCworker;
        UCworker = new DiagramView((string)e.Argument);
        e.Result = UCworker;
        }

    private void Worker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
        {
        UC = (DiagramView)e.Result;
        this.Host.Child = UC;
        }

当它创建新的DiagramView时:

public DiagramView(string path)
    {
        InitializeComponent();

       this.Resize += new EventHandler(this.UpdateSize);
       this.viewer = new AxVisioViewer.AxViewer();
       this.Controls.Add(this.viewer);
       this.viewer.CreateControl();
       this.viewer.Load(path);
       this.viewer.HighQualityRender = false;
       this.viewer.BackColor = Color.White;
       this.viewer.PagetabsVisible = true;
       this.viewer.ContextMenuEnabled = false;
       this.viewer.PropertyDialogEnabled = false;
       this.viewer.ToolbarVisible = true;
       this.viewer.OnSelectionChanged += Viewer_OnSelectionChanged;

    }

对于这一行:

this.viewer = new AxVisioViewer.AxViewer();

我得到:' activeX控件'f8cf7a98-2c45-4c8d-9151-2d716989ddab'无法实例化,因为当前线程不在单线程单元中。'

我了解到背景工作人员无法修改UI元素(如果我输入错了,请纠正我)

我也看到了这个线程:Single-threaded apartment - cannot instantiate ActiveX control

但是我不确定如何实现它(这是STA公寓状态的业务),当我尝试打开文档时,visio查看器简单崩溃了。

我需要一些指导方针来解决这个问题,因为我的目标是要让加载页面与动画一起显示,直到文档完成加载/渲染,以便我可以显示它。

预先感谢您的回答。

更新我还尝试了以下方法

    public partial class TabDiagramView : UserControl,INotifyPropertyChanged
{
    public delegate void DisplayVisio(DiagramView view);
    public DisplayVisio DelegateM;
    DiagramView UC;

    public TabDiagramView()
    {
        InitializeComponent();

        DelegateM = new DisplayVisio(DisplayV);
        Thread t = new Thread(RT);
        t.SetapartmentState(ApartmentState.STA);
        t.IsBackground = true;
        t.Start();          
    }

    #region Thread

    private void RT()
    {
        DiagramView UCworker;
        UCworker = new DiagramView(initialpath);
        Dispatcher.Invoke(DelegateM,UCworker);
    }

    private void DisplayV (DiagramView DiagV)
    {
        UC = DiagV;
        this.Host.Child = DiagV;
    }

但是在这种情况下,当我使用DisplayV方法时,会在UC和this.Host.chilld = DiagV上收到以下消息:System.InvalidOperationException:'跨线程操作无效:从线程访问的控件''而不是创建它的线程。”

tianlingling_2008 回答:WPF-使用Backgroundworker加载Visio文件

根本不可能从另一个线程加载UI控件。但是,如果库提供了线程安全的方法(例如AxViewer.LoadAsync),则可以解决冻结问题,因此使viewer.Load对用户可承受的唯一方法是将viewer.Load的操作延迟到窗口已加载:

string _path;
public DiagramView(string path)
{
    InitializeComponent();

    _path = path;
   this.Resize += new EventHandler(this.UpdateSize);
   this.viewer = new AxVisioViewer.AxViewer();
   this.Controls.Add(this.viewer);
   this.viewer.CreateControl();
   this.viewer.HighQualityRender = false;
   this.viewer.BackColor = Color.White;
   this.viewer.PageTabsVisible = true;
   this.viewer.ContextMenuEnabled = false;
   this.viewer.PropertyDialogEnabled = false;
   this.viewer.ToolbarVisible = true;
   this.viewer.OnSelectionChanged += Viewer_OnSelectionChanged;
   this.Loaded += Viewer_Loaded;
}

private void Viewer_Loaded(object sender,RoutedEventArgs e)
{
    viewer.Load(_path);
}

更重要的是,删除后台工作程序代码。这里没有任何好处。

本文链接:https://www.f2er.com/2617800.html

大家都在问