VSTO任务窗格中的WPF控件的Dispatcher关闭

时间:2014-05-23 07:17:29

标签: wpf multithreading ms-word vsto dispatcher

我们在Windows应用程序级别Addin中的自定义任务窗格中托管的Windows用户控件中托管了WPF控件。

插件有一个带有加载按钮和关闭按钮的功能区。加载按钮将加载文档,然后加载自定义任务窗格并将其与文档窗口关联。

插件代码如下所示

void Ribbon_LoadJob(object sender, EventArgs e) {
    object missing = Type.Missing;
    Globals.ThisAddIn.Application.Documents.Open("C:\\trash\temp.docx", ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
    VstoDocument = Globals.ThisAddIn.Application.ActiveDocument.GetVstoObject();
    VstoDocument.ActiveWindow.Caption = "Current Window";

    //bottom pane is a task pane
    bottomPane = this.CustomTaskPanes.Add(new TaskControl(), "Status");
    // task control is windows control which will be hosted in task pane
    taskControl = (TaskControl)bottomPane.Control;
    bottomPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionBottom;
    bottomPane.Visible = true;

    //Call the WPF control code 
    taskControl.Control.Load();
    VstoDocument.BeforeClose -= vstoDocument_BeforeClose;
}

WPF控制代码如下所示

public partial class TaskControl : UserControl
{
    private DispatcherTimer statusTimer;
    private DateTime workStartTime;

    public string StatusMessage
    {
        set
        {
            this.statusMessage.Text = value;
        }
    }

    public TaskControl()
    {
        InitializeComponent();            
        statusTimer = new DispatcherTimer();
        statusTimer.Tick += statusTimer_Tick;
        statusTimer.Interval = TimeSpan.FromSeconds(1D);
        Unloaded += TaskControl_Unloaded;
        Dispatcher.ShutdownStarted += new EventHandler(Dispatcher_ShutdownStarted);
    }

    void Dispatcher_ShutdownStarted(object sender, EventArgs e)
    {
        TheLogger.Debug("Shutting Down");
    }

    public void Load()
    {
        workStartTime = DateTime.UtcNow;

        Dispatcher.CurrentDispatcher.BeginInvoke(new Action(delegate
        {               
            theStats.Content = string.Format("Current Task: [ {0} ]", "Editing");
            StatusMessage = string.Empty;
            statusTimer.Start();
        }
        ));
    }
    void TaskControl_Unloaded(object sender, RoutedEventArgs e)
    {
        Cleanup();
    }
    private void Cleanup()
    {
        statusTimer.Stop();
        statusTimer.Tick -= statusTimer_Tick;
        statusTimer = null;
        this.Unloaded -= TaskControl_Unloaded;
    }
    private void statusTimer_Tick(object sender, EventArgs e)
    {
        TimeSpan elapsed = DateTime.UtcNow - workStartTime;
        elapsedWorkTime.Content = string.Format("{0:00}:{1:00}",
            elapsed.Minutes, elapsed.Seconds);            
    }
}

当我点击插件上的“加载”按钮时,文档会正确打开,然后屏幕底部的任务窗格显示wpf控件,并显示一个显示时间的计时器。

关闭按钮代码如下所示

 void Ribbon_CloseJob(object sender, EventArgs e)
         {
            object save = true;
            object route = false;
            object format = Word.WdOriginalFormat.wdOriginalDocumentFormat;
            try
            {
                VstoDocument.BeforeClose -= vstoDocument_BeforeClose;
                Globals.ThisAddIn.Application.Caption = "Waiting for user to load again";
                VstoDocument.Close(ref save, ref format, ref route);
                bottomPane.Visible = false;
            }
            catch (Exception e)
            {
               //exception handling 
            }
         }

现在,当我在事件处理程序执行后单击Ribbon中的close时,WPF中的Dispatcher已经开始关闭并触发ShutdownStarted事件。看起来上面的VstoDocument.Close语句会导致调度程序关闭。当我删除该行时,它不会关闭。

这里的问题是过去两年一直在生产相同的代码,并且继续在100多台机器上运行(Windows XP),它永远不会关闭调度程序。然而,在过去的两天里,这只能在两台机器上观察到。

如果有人能够了解为什么调度员在少数机器上关闭文件关闭以及为什么不在大多数机器上关闭,我将不胜感激。如果有人能告诉我是否可以在插件中更改托管WPF控件的调度程序的shutdownmode,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

我在关闭Word中的WPF窗口时遇到了类似的问题。我刚刚调用了Dispatcher.InvokeShutdown方法