C# WPF-使用Backgroundworker加载Visio文件
/免责声明,这是我第一次使用WPF和多线程,如果我犯了一些大错误,请容忍我/ 所以我有一个带有tabcontrol的应用程序。在其中一个选项卡中,我打算通过常用的windows窗体主机+visio viewer activeX控件等加载到visio文件中。。。而且它工作得很好。唯一的问题是,当我加载文档时,UI会冻结20秒(因为我加载的是相当大的文件)。正如我所读到的,这是因为我的应用程序运行在一个简单的线程上。因此,我试图实现一个后台工作程序,以便在后台线程运行时保持UI的反应性 当我实例化UserControl时,我会将其添加到选项卡(Initialpath是visio文件的文件路径): 当它创建新的DiagramView时:C# WPF-使用Backgroundworker加载Visio文件,c#,wpf,multithreading,visio,C#,Wpf,Multithreading,Visio,/免责声明,这是我第一次使用WPF和多线程,如果我犯了一些大错误,请容忍我/ 所以我有一个带有tabcontrol的应用程序。在其中一个选项卡中,我打算通过常用的windows窗体主机+visio viewer activeX控件等加载到visio文件中。。。而且它工作得很好。唯一的问题是,当我加载文档时,UI会冻结20秒(因为我加载的是相当大的文件)。正如我所读到的,这是因为我的应用程序运行在一个简单的线程上。因此,我试图实现一个后台工作程序,以便在后台线程运行时保持UI的反应性 当我实例化U
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“无法实例化,因为当前线程不在单线程单元中。”
我了解到backgroundworker无法修改UI元素(如果我错了,请纠正我)
我还看到了这条线:
但我不知道如何实现它(这是STA公寓状态业务),当我尝试时,visio viewer simple在尝试打开文档时崩溃
我需要一些指导方针来解决这个问题,因为我的目标是在文档加载/渲染完成之前,让加载页面显示动画,以便显示它
提前感谢您的回答
更新:我还尝试了以下方法:
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.child=DiagV上得到以下消息:System.InvalidOperationException:“跨线程操作无效:控件“”从创建它的线程以外的线程访问。”从另一个线程加载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);
}
更重要的是,删除后台工作代码。它在这里没有任何用处。根本不可能从另一个线程加载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);
}
更重要的是,删除后台工作代码。它在这里没有任何用处。如果你告诉我们你在用什么图书馆,会有帮助的?什么是AxVisioViewer.AxViewer?根本不可能从另一个线程加载UI控件。如果该库包含异步加载程序,则可以使用该方法加载而不阻塞UI线程,否则就没有luckHi了!AxVisioViewer.AxViewer只是对Visio Viewer API()的引用,创建的对象是Visio Viewer对象()。我还尝试手动创建一个线程(参见更新),正如我所说的,您不能在另一个线程中创建控件。库应该提供线程安全的方法,否则就无法实现。最接近实现它的方法是只在另一个线程中放入Load(),但我认为如果您告诉我们您使用的是什么库,这不会有帮助?什么是AxVisioViewer.AxViewer?根本不可能从另一个线程加载UI控件。如果该库包含异步加载程序,则可以使用该方法加载而不阻塞UI线程,否则就没有luckHi了!AxVisioViewer.AxViewer只是对Visio Viewer API()的引用,创建的对象是Visio Viewer对象()。我还尝试手动创建一个线程(参见更新),正如我所说的,您不能在另一个线程中创建控件。库应该提供线程安全的方法,否则就无法实现。最接近实现它的方法是在另一个线程中只放入Load(),但我认为这不起作用