Word Application在执行Documents.Open(ref filename)方法和处理Application.DocumentOpen事件时挂起

时间:2013-05-28 14:00:10

标签: c# ms-word office-interop hang

我已经创建了一个用户控件(Windows窗体应用程序)来获取Word的实例(活动或新的),并提供一个按钮,使用文件对话框选择器将文档打开到该实例中。

表单包含2个按钮,1个用于获取单词实例,另一个用于打开文档。它还包含一个用于显示打开文档的列表框,以及一个openfiledialog控件,用于提供选择要打开的文档的方法。

我正在处理Application.DocumentOpen事件以填充列表框......

m_wordApp.DocumentOpen += new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);

我确定何时需要重新调用填充列表框的方法,以确保对控件的访问位于创建它的同一个线程上....

private void AddDocument(string name)
{
    try
    {
        if (m_documentsListBox.InvokeRequired && m_documentsListBox.IsHandleCreated&&!m_documentsListBox.IsDisposed)
        {
            this.Invoke(m_AddDocument, new object[] { name });
            return;
        }

        if (!m_documentsListBox.Items.Contains(name))
            m_documentsListBox.Items.Add(name);
    }
    catch (Exception ex)
    {
    }
}

我没有使用2个点,我相信我正确地释放任何COM对象。

为什么应用程序会挂起打开文档的代码行...

WordDoc = m_wordDocs.Open(ref fileName);

或重新调用AddDocument()方法的行......

this.Invoke(m_AddDocument, new object[] { name });
在某个地方,我认为我必须遇到一个线程问题,因为如果我选择使用按钮而不是直接在Word应用程序中打开文档,则只会发生挂起。

以下完整代码......


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;

//  use these for the core office & word references
using msoWord = Microsoft.Office.Interop.Word;


namespace MCDevNET.Office.Word.TestUIControls
{
    public partial class OpenWordDocument : Form
    {
        public OpenWordDocument()
        {
            InitializeComponent();

            m_openWordButton.Click += new EventHandler(buttonOpenWordApp_Click);
            m_openDocumentButton.Click += new EventHandler(buttonOpenDocument_Click);

            m_AddDocument = new UpdateListControl(AddDocument);
        }

        #region Form: control eventHandlers

        void buttonOpenWordApp_Click(object sender, EventArgs e)
        {
            try
            {
                if (!IsValid(m_wordApp))
                    WordApp = GetInstance();
                AddAllDocuments();
            }
            catch (Exception ex)
            {
            }
        }

        void buttonOpenDocument_Click(object sender, EventArgs e)
        {
            OpenWordDoc();
        }

        public delegate void UpdateListControl(string name);
        private UpdateListControl m_AddDocument;

    private void AddDocument(string name)
    {
        try
        {
            if (m_documentsListBox.InvokeRequired && m_documentsListBox.IsHandleCreated&&!m_documentsListBox.IsDisposed)
            {
                this.Invoke(m_AddDocument, new object[] { name });
                return;
            }

            if (!m_documentsListBox.Items.Contains(name))
                m_documentsListBox.Items.Add(name);
        }
        catch (Exception ex)
        {
        }
    }

        private void AddAllDocuments()
        {
            try
            {
                m_documentsListBox.Items.Clear();
                if (m_wordDocs != null)
                {
                    for (int i = 1; i <= m_wordDocs.Count; i++)
                        AddDocument(m_wordDocs[i].Name);
                }
            }
            catch (Exception ex)
            {
            }
        }

        #endregion


        #region Word: properties & eventhandlers

        private msoWord.Document m_wordDoc;
        public msoWord.Document WordDoc
        {
            get { return m_wordDoc; }
            private set
            {
                try
                {
                    if (m_wordDoc != value)
                    {
                        ReleaseCOMObject(m_wordDoc);
                        m_wordDoc = value;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        private msoWord.Documents m_wordDocs;
        public msoWord.Documents WordDocs
        {
            get { return m_wordDocs; }
            private set
            {
                try
                {
                    if (m_wordDocs != value)
                    {
                        ReleaseCOMObject(m_wordDocs);
                        m_wordDocs = value;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        private msoWord.Application m_wordApp;
        public msoWord.Application WordApp
        {
            get { return m_wordApp; }
            set
            {
                try
                {
                    if (m_wordApp != value)
                    {
                        if (m_wordApp != null)
                        {
                            m_wordApp.DocumentOpen -= new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
                            ReleaseCOMObject(m_wordApp);
                        }

                        m_wordApp = value;

                        if (IsValid(m_wordApp))
                        {
    m_wordApp.DocumentOpen += new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
                            WordDocs = m_wordApp.Documents;
                        }
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        void m_wordApp_DocumentOpen(msoWord.Document doc)
        {
            try
            {
                string name = doc.Name;
                AddDocument(name);
            }
            catch (Exception ex)
            {
            }
            finally
            {
                ReleaseCOMObject(doc);
                doc = null;
            }
        }

        private msoWord.Application GetInstance()
        {
            msoWord.Application app = null;
            try
            {
                app = (msoWord.Application)Marshal.GetActiveObject("Word.Application");
            }
            catch (Exception ex)
            {
                if (app == null)
                    app = new msoWord.Application();
            }
            finally
            {
                if (IsValid(app))
                {
                    app.Visible = true;
                    app.Activate();
                }
            }
            return app;
        }

        private void OpenWordDoc()
        {
            try
            {
                m_openFileDialog.AddExtension = true;
                m_openFileDialog.Filter = "All Word (*.docx; *.docm; *.doc; *.dotx; *.dotm; *.dot)|*.docx;*.docm;*.doc;*.dotx;*.dotm;*.dot|Word Documents (*.docx)|*.docx|Word Macro-Enabled Documents (*.docm)|*.docm|Word 97-2003 Documents (*.doc)|*.doc|All Word Templates (*.dotx; *.dotm; *.dot)|*.dotx;*.dotm;*.dot|Word Templates (*.dotx)|*.dotx|Word Macro-Enabled Templates (*.dotm)|*.dotm)";
                m_openFileDialog.FilterIndex = 1;
                m_openFileDialog.Multiselect = false;
                m_openFileDialog.Title = "Open Word Document";

                if (m_openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    object fileName = m_openFileDialog.FileName;
                    WordDoc = m_wordDocs.Open(ref fileName);
                }
            }
            catch (Exception ex)
            {
            }
        }

        private bool IsValid(msoWord.Application app)
        {
            try
            {
                if (app != null)
                {
                    string name = app.Caption;
                    return true;
                }
            }
            catch (Exception ex)
            {
            }
            return false;
        }
        #endregion

        private void ReleaseCOMObject(object comObject)
        {
            try
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();

                if (comObject != null && Marshal.IsComObject(comObject))
                    Marshal.ReleaseComObject(comObject);

            }
            catch (Exception ex)
            {
            }
        }
    }
}
namespace MCDevNET.Office.Word.TestUIControls
{
    partial class OpenWordDocument
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.m_documentsListBox = new System.Windows.Forms.ListBox();
            this.m_openDocumentButton = new System.Windows.Forms.Button();
            this.m_openWordButton = new System.Windows.Forms.Button();
            this.m_openFileDialog = new System.Windows.Forms.OpenFileDialog();
            this.SuspendLayout();
            // 
            // lb_Documents
            // 
            this.m_documentsListBox.FormattingEnabled = true;
            this.m_documentsListBox.Location = new System.Drawing.Point(12, 41);
            this.m_documentsListBox.Name = "lb_Documents";
            this.m_documentsListBox.Size = new System.Drawing.Size(156, 134);
            this.m_documentsListBox.TabIndex = 8;
            // 
            // m_openDocumentButton
            // 
            this.m_openDocumentButton.Location = new System.Drawing.Point(93, 12);
            this.m_openDocumentButton.Name = "m_openDocumentButton";
            this.m_openDocumentButton.Size = new System.Drawing.Size(75, 23);
            this.m_openDocumentButton.TabIndex = 7;
            this.m_openDocumentButton.Text = "Doc";
            this.m_openDocumentButton.UseVisualStyleBackColor = true;
            // 
            // m_openWordButton
            // 
            this.m_openWordButton.Location = new System.Drawing.Point(12, 12);
            this.m_openWordButton.Name = "m_openWordButton";
            this.m_openWordButton.Size = new System.Drawing.Size(75, 23);
            this.m_openWordButton.TabIndex = 6;
            this.m_openWordButton.Text = "Word";
            this.m_openWordButton.UseVisualStyleBackColor = true;
            // 
            // m_openFileDialog
            // 
            this.m_openFileDialog.FileName = "openFileDialog1";
            // 
            // OpenWordDocument
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(182, 184);
            this.Controls.Add(this.m_documentsListBox);
            this.Controls.Add(this.m_openDocumentButton);
            this.Controls.Add(this.m_openWordButton);
            this.Name = "OpenWordDocument";
            this.Text = "OpenWordDocument";
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.ListBox m_documentsListBox;
        private System.Windows.Forms.Button m_openDocumentButton;
        private System.Windows.Forms.Button m_openWordButton;
        private System.Windows.Forms.OpenFileDialog m_openFileDialog;
    }
}

1 个答案:

答案 0 :(得分:1)

挂断发生在对Documents.Open(fileName)

的调用上

您为Application.DocumentOpen事件连接了一个事件处理程序。在删除此事件处理程序时,不再发生挂起。

我认为问题的原因是你在Documents.Open调用返回之前尝试触发该事件时遇到了死锁。这意味着处理事件的线程仍然很忙。

更换

WordDoc = m_wordDocs.Open(ref fileName)

 new System.Threading.Tasks.Task(() => WordDoc = m_wordDocs.Open(ref fileName))
                           .Start();

在另一个线程上打开文档似乎可以解决问题。