从另一个线程更新Excel电子表格

我已经使用C#创buildCOM服务器,我的客户端可以接收实时更新。 更新通常从不同的线程发起。 但我注意到,当callback方法更新电子表格时,Excel崩溃。 有什么办法在UI线程中调用更新?

PS我知道Excel的RTDfunction。 但它不适合我的需要,因为我需要一个更新中的几个参数。

你正在寻找的是ISyncronizedInvoke的Invoke / BeginInvoke方法

在你的用户界面线程,采取任意控制,并保持该参考…

从想要触发更新的线程调用该控件上的Invoke或BeginInvoke(Control实现ISyncronizedInvoke),并使用要在UI线程上执行的委托…从该委托中调用您的COM服务器

//编辑:示例代码

using System; using System.Windows.Forms; using System.Threading; using Microsoft.Office.Interop.Excel; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { Thread someWorkerThread; Microsoft.Office.Interop.Excel.Application ExApp; Worksheet wrkSheet; public Form1() { InitializeComponent(); ExApp = new Microsoft.Office.Interop.Excel.Application(); ExApp.Visible = true; // or else we won't see the window var books = ExApp.Workbooks; var wrkBook = books.Add(); var sheets = wrkBook.Worksheets; wrkSheet = sheets.get_Item(1); Marshal.ReleaseComObject(sheets); Marshal.ReleaseComObject(wrkBook); Marshal.ReleaseComObject(books); someWorkerThread = new Thread(new ParameterizedThreadStart(threadHandler)); someWorkerThread.Start(this); } private void threadHandler(object obj) {// this will be executed on a seperate worker thread Control mainFrm = obj as Control; if (mainFrm == null) throw new ArgumentException("Need to have a Control as parameter"); for (int i = 1; i < 50;i++ ) { Thread.Sleep(2500); mainFrm.Invoke(new Action<int>(doStuff), i); // this will invoke the main UI thread } } private void doStuff(int i) {// this will be executed on the main UI thread var range = wrkSheet.Range[string.Format("A{0}", i)]; range.Value = "Hello World!"; Marshal.ReleaseComObject(range); } #region designer stuff /// <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.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(76, 84); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(149, 13); this.label1.TabIndex = 0; this.label1.Text = "I am an ordinary windows form"; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 262); this.Controls.Add(this.label1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; #endregion } } 

被build议:这个例子没有清理wrkSheet引用和ExApp引用…你必须在退出你的应用程序之前释放它们