2011-02-24 4 views
1

COM을 통해 노출 된 다음 VB.NET 3.5의 실험 어셈블리를 작성하고 (일부러 작성하는 방법을 가르치고 있습니다.) 일부 Excel VBA 코드에서 호출하여 인스턴스를 시작합니다. 클래스는 일부 Excel 이벤트를 트랩 한 다음 Excel의 활성 통합 문서에서 일부 기능을 수행합니다.BackgroundWorker를 통해 Excel과 상호 작용하는 .NET COM 어셈블리

클래스를 시작하려면 Excel 응용 프로그램에 대한 참조가 VBA에서 전달됩니다 (어셈블리에서 Excel 용 PIA를 사용하고 있습니다).

내 어셈블리에서 시간이 많이 걸리는 작업을 수행해야하므로 BackgroundWorker을 WinForm에 사용하여 작업이 백그라운드에서 완료되면 작업 진행률 대화 상자를 표시 할 수 있습니다.

이런 식으로 백그라운드 작업자를 사용하여 COM을 통해 Excel과 상호 작용할 때 문제가 있는지 알고 싶습니다. 요청하는 이유는 어셈블리의 주 클래스가 Excel 응용 프로그램 개체에 대한 참조를 보유하고 있기 때문에 활성 워크 북을 판별 한 다음 여기에서 일부 작업을 수행 할 수 있도록 BackgroundWorker으로 전달됩니다. 하나의 절차를 통해서만 통합 문서 자체 (다른 개체가 아님)에 액세스하고 있습니다.

나는 Excel에서이 부분이 마음에 들지 않을 수도 있음을 알고 있습니다.

+0

닫을 표가 몇 개 있습니다. 왜 이것이 '진정한 질문'이 아닌지 나는 알지 못합니다. 묻는 사람은 무언가가 합법적인지 또는 버그인지 물어 봅니다. "이 방법으로 백그라운드 작업자를 사용하여 COM을 통해 Excel과 상호 작용할 때 발생하는 문제 [?]" –

+0

예, 맞습니다. 문제가 있습니까? 아니면 Excel과 상호 작용할 수있는 더 좋은 방법이 있습니까? 아마 내가 질문을 더 잘 표현 했어야했는데 ...! –

답변

2

당신이로 다스 려하는 경우 :

  • 가에 대한 참조를 통해 (또는 작업자 스레드) 새 스레드 떨어져 당신의 VB.NET 코드에
  • 스핀을 VBA에서 메서드 호출을 얻기과 나눠 통합 문서 (또는 Excel.Application, 범위에 상관 없음) (매개 변수, 통계 ... 중요하지 않음)
  • 백그라운드 스레드가 Excel에 액세스하는 동안 원래 스레드를 사용하여 UI 표시

그런 다음 , 아니; 너는 그렇게 할 수 없다.

Excel VBA는 STA 환경입니다. Excel 개체 모델에 대한 모든 액세스는 같은 스레드에서 발생해야합니다. 스레드를 선택하지 않아도됩니다. 그것은 당신의 메소드를 호출하는 스레드 여야합니다.

작업자 스레드에서 Excel에 액세스하는 코드를 실행하려면 작업자 스레드에 대한 인터페이스 포인터를 "마샬링"해야합니다. Mashalling은 필요에 따라 스레드 간 메서드 호출을 연결하는 COM 래퍼 ('프록시/스텁'쌍이라고 함)를 만듭니다. 이는 .NET에서 Form.Invoke() 메서드를 사용할 때 발생하는 것과 유사합니다. 나는 .NET에서 그것을하는 방법을 머리 꼭대기에서 알 수 없다. 어쨌든 이것은 내 첫 번째 접근 방식이 아닙니다.

또 다른 방법은 작업자 스레드에서 Excel 개체에 액세스하는 것이 아니라 기본 양식 개체에서 도우미를 사용하는 것입니다 (양식을 원하십니까?). 작업자 스레드가 Form.Invoke()을 통해 해당 도우미를 호출하여 UI 스레드 (VBA에서 호출 한 스레드)에서 실행되도록하십시오. 이것은 COM이 아니라 .NET이 작업을한다는 점을 제외하고는 기능상 첫 번째 대안과 동일합니다.

세 번째 접근법은 작업자 스레드를 전혀 사용하지 않는 것입니다. VB 방식으로 수행하십시오. 유일한 스레드에서만 UI를 작성하십시오. 그것을 보여주고 양식의 Load 행사에서 당신의 일을하십시오.을 잠시 (1 초에 몇 번) 호출하여 UI가 일부 연구의 매끄러움으로 작동하게하십시오.

네 번째 대안은 문제를 해결하는 것입니다. 풀 스레드 (새로운 스레드를 BackgroundWorker에서 얻은 것) 대신 사용하고 거기에서 UI를 처리하십시오. 여기서는 역할을 바꿉니다. 주 스레드는 멋진 작업을 수행하고, 추가 스레드는 양식을 만들고 UI를 보여줍니다. 다시 Form.Invoke()을 사용하여 진행률 창을 업데이트하십시오. 완료되면 Dispose() 스레드를 확인하십시오. 이것은 내가 선호하는 접근 일 수 있습니다.

그냥 모래 시계 마우스 포인터를 사용하면 ... "천천히"천천히 "천천히"무엇입니까?

+0

우수! 조언을 많이 주셔서 감사합니다, 그것은 나를 생각있어 :) –

0

BackgroundWorker 사용에 대해 잘 모릅니다. 필자는 PIA와 COM을 통해 Excel에 인터페이스 된 Winforms 응용 프로그램을 작성했습니다. 평범한 오래된 ThreadStart 델리게이트를 사용하여 배경에로드 된 파일이있는 동안 진행률 표시 줄을 보여주는 스레드를 회전시킵니다. 잘 했어. 내가 이해할 때, BackgroundWorker는 커버 아래에서 거의 똑같이 작동하므로, 나는 그것에 대해 말할 것이다.

관련 문제