COM 상호 운용성을 사용하여 개체의 수명 주기를 처리하는 가장 효율적인 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/95834

문제

COM 자동화를 위해 작성한 클래스를 사용하는 Windows 워크플로 응용 프로그램이 있습니다.COM을 사용하여 수업에서 Word와 Excel을 엽니다.

현재 COM 도우미에서 IDisposable을 구현하고 있으며 Marshal.ReleaseComObject()를 사용하고 있습니다.그러나 워크플로가 실패하면 Dispose() 메서드가 호출되지 않고 Word 또는 Excel 핸들이 열린 상태로 유지되며 응용 프로그램이 중단됩니다.

이 문제에 대한 해결책은 매우 간단하지만 단순히 문제를 해결하기보다는 무언가를 배우고 COM을 사용하는 올바른 방법에 대한 통찰력을 얻고 싶습니다.저는 COM 핸들을 소유한 클래스의 수명 주기를 처리하는 "최상의" 또는 가장 효율적이고 안전한 방법을 찾고 있습니다.패턴, 모범 사례 또는 샘플 코드가 도움이 될 것입니다.

도움이 되었습니까?

해결책

Dispose() 메서드를 호출하지 않는 오류가 무엇인지 알 수 없습니다.예외를 발생시키는 코드 활동만 포함하고 내 워크플로의 Dispose() 메서드가 두 번 호출되는 순차 워크플로를 사용하여 테스트를 수행했습니다. 이는 표준 WorkflowTerminating 이벤트 처리기 때문입니다.다음 코드를 확인하세요.

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();
        }
    }

워크플로우1.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.");
            }
        }
    }

뭔가 빠졌나요?활동(및 결과적으로 워크플로) 개체의 수명 주기 관련 메서드에 대해서는 다음 게시물을 확인하세요. 활동 "평생" 방법.폐기에 관한 일반적인 기사를 원한다면 다음을 확인하세요. 이것.

다른 팁

기본적으로 작업이 끝날 때 개체에 대해 Dispose()를 호출하기 위해 수동 코드에 의존해서는 안 됩니다.아마도 지금 당장 다음과 같은 일이 있을 것입니다.

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

대신, try 블록을 사용하여 트리거될 수 있는 모든 예외를 포착하고 해당 시점에서 dispose를 호출해야 합니다.이것은 표준적인 방법입니다:

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

이것은 그래서 일반적으로 C#에는 다음을 생성하는 특수 구문이 있습니다. 똑같은 코드 [참고 참조] 위에 표시된 것처럼;이것은 대부분의 시간 동안 수행해야 하는 작업입니다(위와 같은 수동 패턴을 작업하기 쉽게 만드는 특별한 개체 구성 의미가 없는 경우).

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

편집하다:
메모:생성된 실제 코드는 위의 두 번째 예제보다 약간 더 복잡합니다. using 차단하다.이는 두 번째 코드 블록이 { }로 둘러싸인 것과 같습니다.설명의 명확성을 위해 생략했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top