Question

J'ai une application Windows Workflow qui utilise les classes que j'ai écrites pour l'automatisation COM. J'ouvre Word et Excel depuis mes cours avec COM.

Je suis en train de mettre en place IDisposable dans mon assistant COM et d’utiliser Marshal.ReleaseComObject (). Toutefois, si mon workflow échoue, la méthode Dispose () n'est pas appelée et les poignées Word ou Excel restent ouvertes et mon application se bloque.

La solution à ce problème est assez simple, mais plutôt que de simplement la résoudre, j'aimerais apprendre quelque chose et avoir un aperçu de la bonne façon de travailler avec COM. Je cherche le "meilleur" ou le moyen le plus efficace et le plus sûr de gérer le cycle de vie des classes propriétaires des descripteurs COM. Des modèles, des pratiques recommandées ou des exemples de code seraient utiles.

Était-ce utile?

La solution

Je ne vois pas quel échec vous n’appelez pas la méthode Dispose (). J'ai fait un test avec un flux de travail séquentiel ne contenant qu'une activité de code qui lève simplement une exception et la méthode Dispose () de mon flux de travail est appelée deux fois (c'est à cause du gestionnaire d'événements standard WorkflowTerminated). Vérifiez le code suivant:

Program.cs

    class Program
    {
        static void Main(string[] args)
        {
            using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) 
                {
                    waitHandle.Set();
                };
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
                {
                    Console.WriteLine(e.Exception.Message);
                    waitHandle.Set();
                };

                WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication1.Workflow1));
                instance.Start();

                waitHandle.WaitOne();
            }
            Console.ReadKey();
        }
    }

Workflow1.cs

    public sealed partial class Workflow1: SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
            this.codeActivity1.ExecuteCode += new System.EventHandler(this.codeActivity1_ExecuteCode);
        }

        [DebuggerStepThrough()]
        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("Throw ApplicationException.");
            throw new ApplicationException();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Here you must free your resources 
                // by calling your COM helper Dispose() method
                Console.WriteLine("Object disposed.");
            }
        }
    }

Est-ce que je manque quelque chose? En ce qui concerne les méthodes liées au cycle de vie d'un objet Activity (et par conséquent d'un workflow), veuillez vérifier cet article: Activité " Durée de vie " Méthodes . Si vous souhaitez simplement un article générique sur la suppression, consultez this . / p>

Autres conseils

En principe, vous ne devez pas vous fier au code manuel pour appeler Dispose () sur votre objet à la fin du travail. Vous avez probablement quelque chose comme ça en ce moment:

MyComHelper helper = new MyComHelper();
helper.DoStuffWithExcel();
helper.Dispose();
...

À la place, vous devez utiliser des blocs try pour intercepter toute exception pouvant être déclenchée et appeler disposition à ce stade. C'est la manière canonique:

MyComHelper helper = new MyComHelper();
try
{
    helper.DoStuffWithExcel();
}
finally()
{
    helper.Dispose();
}

C’est donc commun que C # ait une construction spéciale qui génère le même code exact [voir la note] comme indiqué ci-dessus; C’est ce que vous devriez faire la plupart du temps (sauf si vous avez une sémantique spéciale pour la construction d’objets qui rend plus facile le travail sur un modèle manuel comme celui ci-dessus):

using(MyComHelper helper = new MyComHelper())
{
    helper.DoStuffWithExcel();
}

MODIFIER :
REMARQUE: le code généré est un peu plus compliqué que le deuxième exemple ci-dessus, car il introduit également une nouvelle portée locale qui rend l'objet d'assistance indisponible après le bloc utilisant . C'est comme si le second bloc de code était entouré de {}. Cela a été omis pour clarifier l'explication.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top