Condividi tramite


Supporto del modello di threading nei progetti di InfoPath tramite il modello a oggetti di InfoPath 2003

Gli oggetti COM a cui si accede tramite gli assembly di interoperabilità Microsoft.Office.Interop.InfoPath.dll, Microsoft.Office.Interop.InfoPath.SemiTrust.dll e Microsoft.Office.Interop.InfoPath.Xml.dll installati da Microsoft Office InfoPath 2007 non supportano le chiamate eseguite su più thread, incluse le interfacce per Microsoft XML Core Services (MSXML) 5.0 relative agli oggetti di Office contenute nello spazio dei nomi Microsoft.Office.Interop.InfoPath.SemiTrust (la maggior parte hanno nomi con prefisso IXMLDOM) e tutte le interfacce esposte dallo spazio dei nomi Microsoft.Office.Interop.InfoPath.Xml, nessuna delle quali è thread-safe.

Tutte le chiamate a tali oggetti COM devono essere eseguite su un singolo thread. Il codice gestito di un progetto di InfoPath può creare altri thread per eseguire operazioni in background, ma il codice in esecuzione su thread diversi dal thread principale non può eseguire chiamate ai modelli a oggetti di InfoPath.

Se un progetto con codice gestito di InfoPath utilizza più thread, è necessario prestare attenzione quando si condividono gli oggetti tra i thread. Evitare di condividere tra i thread i riferimenti al modello DOM (Document Object Model) XML o i riferimenti agli oggetti di InfoPath.

Esecuzione di chiamate asincrone al modello a oggetti di InfoPath

Nei casi in cui è necessario chiamare un processo quale un timer in esecuzione su un thread distinto, è possibile ovviare al fatto che il modello a oggetti di InfoPath non supporta tali chiamate.

Nell'esempio seguente viene creata un'istanza System.Timers.Timer nel metodo _Startup del modulo e viene associata una richiamata asincrona al timer. Viene inoltre creata un'istanza invisibile del form Windows (System.Windows.Forms.Form). Quando la funzione di richiamata in base al tempo trascorso viene eseguita una volta al secondo, chiama la funzione PostMessage Win32 per inviare un messaggio alla finestra invisibile. Quest'ultima include una funzione WndProc che elabora il messaggio ricevuto dalla funzione di richiamata del timer e aggiorna il modello DOM XML del modulo. Per poter essere eseguito, il modulo deve essere installato come modulo completamente attendibile. Per informazioni sul debug di un modello di modulo completamente attendibile, vedere Procedura: Eseguire la visualizzazione in anteprima e il debug dei modelli di modulo con codice gestito che richiedono l'attendibilità completa. Per informazioni sulla distribuzione di un modello di modulo completamente attendibile, vedere Procedura: Distribuire progetti di 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='https://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);
        }
    }
}