c# - Word 应用程序在执行 Documents.Open(ref filename) 方法和处理 Application.DocumentOpen 事件时挂起

标签 c# ms-word office-interop freeze

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

该表单包含 2 个按钮,一个用于获取单词实例,另一个用于打开文档。它还包含一个用于显示打开的文档的列表框,以及一个用于提供选择要打开的文档的方法的 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;
    }
}

最佳答案

挂起发生在对 Documents.Open(fileName) 的调用上

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

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

替换

WordDoc = m_wordDocs.Open(ref fileName)

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

在不同线程上打开文档似乎可以解决问题。

关于c# - Word 应用程序在执行 Documents.Open(ref filename) 方法和处理 Application.DocumentOpen 事件时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16794056/

相关文章:

c# - 如何以独立于区域设置的方式定位本地组?

c# - 处理类和 NHibernate 实体中的集合属性

c# - 适当的互操作清理

c# - 使用SQLite数据库的MS Word邮件合并

c# - 为什么 Outlook 在使用 Office 互操作时崩溃?

c# - 在 GridView 中为复选框列生成新列

c# - 为什么没有在 app.config 中配置 ConsoleAppender 导致日志写入控制台?

vba - 如何检查直到文件存在

c# - 在 MS Word 中获取单元格颜色

c# - 在word文档的页脚中添加从第n页开始的页码