2012-10-22 54 views
1

此C#代碼是在.NET 4.5 ComVisible組件:Excel VBA中無法調用COM方法(在.NET內置),其使用多線程

C#代碼

[InterfaceType(ComInterfaceType.InterfaceIsDual)] 
[Guid("22341223-9264-12AB-C1B4-B4F112014C31")] 
public interface IComWithTask 
{ 
    void LongExecutionMethod(double x); 
    void LongExecutionMethodAsync(double x); 
} 

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
[Guid("23844123-9274-12CB-C1F4-B4F1521E4F33")] 
public interface IComWithTaskEvents 
{ 
    void OnLongExecutionMethodComplete(double x); 
} 

[ClassInterface(ClassInterfaceType.None)] 
[ComSourceInterfaces(typeof(IComWithTaskEvents))] 
[Guid("E4F27AA4-1932-2196-1234-121CF2722C42")] 
[ProgId("ComWithTask")] 
public class ComWithTask : IComWithTask 
{ 
    [ComVisible(false)] 
    public delegate void LongExecutionMethodComplete(double x); 
    public event LongExecutionMethodComplete OnLongExecutionMethodComplete; 

    public void LongExecutionMethod(double x) 
    { 
     if (OnLongExecutionMethodComplete != null) 
     { 
      OnLongExecutionMethodComplete(x * x); 
     } 
    } 

    public void LongExecutionMethodAsync(double x) 
    { 
     Task.Factory.StartNew(state => 
     { 
      var onLongExecutionMethodComplete = OnLongExecutionMethodComplete; 
      if (onLongExecutionMethodComplete != null) 
      { 
       onLongExecutionMethodComplete(x * x); 
      } 
     }, null); 
    } 
} 

從Excel 2010中的32位VBA ,我有以下行爲:

VBA代碼

Private WithEvents oComWithTask As ComWithTask 

Public Sub Class_Initialize() 
    Set oComWithTask = New ComWithTask 
End Sub 

Public Sub LongExecutionMethod() 
    ' Works as expected 
    Call oComWithTask.LongExecutionMethod(2) 
End Sub 

Public Sub LongExecutionMethodAsync() 
    ' Does NOT work! 
    Call oComWithTask.LongExecutionMethodAsync(3) 
End Sub 

Private Sub oComWithTask_OnLongExecutionMethodComplete(ByVal x As Double) 
    MsgBox x 
End Sub 

我知道,我紡一個線程我在調用LongExecutionMethodAsync時,nside .NET,我知道辦公應用程序是單線程的。

我的確發現了一個很好的關於從.NET以多線程的方式調用COM組件的文獻,但找不到任何相反的資源,即VBA調用使用COM方法包裝的多線程.NET。

如何使LongExecutionMethodAsync工作, 多線程,你可以點我到任何相關的資源在這個 主題有什麼想法? 另外,您是否有其他建議來觸發VBA中的異步事件?

+0

使用BackgroundWorker。在RunWorkerCompleted事件處理程序中觸發事件。 –

+0

您可能沒有同步提供程序。檢查System.Threading.SynchronizationContext.Current的值。如果它爲空,則事件處理程序將在錯誤的線程上運行。與TPL同樣的問題。你可以在你的初始化代碼中創建一個隱藏的Winforms表單對象來獲取提供者。 –

+0

@HansPassant,我已經更新了上面的代碼以反映我的'BackgroundWorker'的實現。 'SynchronizationContext'爲null,但我不在Winform環境中,爲此添加WinForm庫會很詭異。這是一個COM/.NET庫,它將向Excel中添加一些功能,但沒有GUI。 – Adam

回答

1

上面的代碼正常工作,問題是VBA中的對象的壽命在事件引發之前即將死亡。

相關問題