共用方式為


使用 InfoPath 2003 物件模型在 InfoPath 專案中支援執行緒

透過 Microsoft.Office.Interop.InfoPath.dll、Microsoft.Office.Interop.InfoPath.SemiTrust.dll 及 Microsoft.Office.Interop.InfoPath.Xml.dll interop 組件 (由 Microsoft InfoPath 所安裝) 來存取的 COM 物件,並不支援多執行緒的呼叫。 這包括 Microsoft XML Core Services (MSXML) 物件的介面,這些介面是由 Microsoft.Office.Interop.InfoPath.SemiTrust 命名空間 (其中大多數都具有以 IXMLDOM 字元開頭的名稱) 所包裝的,而且所有的介面都由 Microsoft.Office.Interop.InfoPath.Xml 命名空間公開,這些介面都不是安全執行緒。

對這些 COM 物件所做出的呼叫必須是在單一的執行緒上發出。 在 InfoPath 專案中的 Managed 程式碼可以建立其他的執行緒以執行背景工作,但是在非主要執行緒以外的執行緒上所執行的程式碼則無法呼叫 InfoPath 物件模型。

如果您的 InfoPath Managed 程式碼專案使用多個執行緒,則在執行緒間共用物件必須非常小心。 您不能在執行緒間共用「XML 文件物件模型」(DOM) 的參照或 InfoPath 物件的參照。

對 InfoPath 物件模型進行非同步呼叫

至於需要在程序中呼叫的情況,例如在個別執行緒執行的計時器,想要解決 InfoPath 物件模型不支援此種呼叫的狀況是有可能的。

下列範例會在表單的 _Startup 方法中建立 System.Timers.Timer 執行個體,並將非同步的回呼連結至計時器。 此外,還會建立一個隱藏的視窗表單 (System.Windows.Forms.Form) 執行個體。 計時器每經過一秒,回呼函數也會執行一次,它會呼叫 Win32 PostMessage 函數,將訊息貼至隱藏的視窗。 這個隱藏視窗含有一個 WndProc 函數,以便處理從計時器回呼函數收到的訊息,並更新表單的 XML 文件物件模型 (DOM)。 此表單必須安裝為完全信任的表單,才能夠執行。 如需偵錯完全信任窗體範本的資訊,請參閱 需要完全信任的預覽和偵錯窗體範本。 如需部署完全信任表單範本的資訊,請參閱 使用程式碼部署 InfoPath 窗體範本

using System;
using Microsoft.Office.Interop.InfoPath.SemiTrust;
using System.Timers;
using System.Runtime.InteropServices;
// Office integration attribute. Identifies the startup class for the
// form. Do not modify.
[assembly: System.ComponentModel.DescriptionAttribute("InfoPathStartupClass, Version=1.0, Class=AsyncUpdate.AsyncUpdate")]
namespace AsyncUpdate
{
    public class User32
    {
        [DllImport("User32.dll")]
        public static extern Int32 PostMessage(
            IntPtr hWnd, int Msg, int wParam, int lParam);
        public User32()
        {    
        }
        ~User32()
        {
        }
    }
    public class MyWindow : System.Windows.Forms.Form
    {
        private XDocument thisXDocument;
        private AsyncUpdate thisProcess ;
        // Private message for internal class.
        public const int WM_MYNOTIFY = 0x400;
        public MyWindow(XDocument doc, AsyncUpdate process)
        {
            thisXDocument = doc;
            thisProcess  = process;
            this.Text = "MyWindow";
            // Force HWND to get created in Win32
            IntPtr hwnd = this.Handle; 
        }
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
        protected override void WndProc(
            ref System.Windows.Forms.Message m) 
        {
            switch (m.Msg)
            {
            case WM_MYNOTIFY:
                IXMLDOMNode xml = thisXDocument.DOM.selectSingleNode(
                    "/my:myFields/my:field1");
                xml.text = thisProcess.counter.ToString();
                break;                
            }
            base.WndProc(ref m);
        }
    }
    // The namespace prefixes defined in this attribute must remain 
    // synchronized with those in the form definition file (.xsf).
    [InfoPathNamespace("xmlns:my='http://schemas.microsoft.com/office/infopath/2003/myXSD/2004-02-11T23-29-59'")]
    public class AsyncUpdate
    {
        private XDocument thisXDocument;
        private Application thisApplication;
        public int counter;
        private System.Timers.Timer myTimer;
        private MyWindow myWnd;
    
        public void _Startup(Application app, XDocument doc)
        {
            thisXDocument = doc;
            thisApplication = app;
            // init the counter
            counter = 0;
            // Start a timer on another thread
            myTimer = new System.Timers.Timer(1000);
            myTimer.Elapsed += new ElapsedEventHandler(
                myTimer_Elapsed);
            myTimer.Start();
            // create hidden window to receive notifications 
            // back on the main thread
            myWnd = new MyWindow(thisXDocument, this);
        }
        public void _Shutdown()
        {
            myWnd.Dispose();
            myTimer.Stop();
            myTimer.Dispose();
        }
        private void myTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            // This method is called on a second thread
            counter ++;
            // Post message back to main thread
            User32.PostMessage(
                myWnd.Handle, MyWindow.WM_MYNOTIFY, 0, 0);
        }
    }
}