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中的异步事件?
使用BackgroundWorker。在RunWorkerCompleted事件处理程序中触发事件。 –
您可能没有同步提供程序。检查System.Threading.SynchronizationContext.Current的值。如果它为空,则事件处理程序将在错误的线程上运行。与TPL同样的问题。你可以在你的初始化代码中创建一个隐藏的Winforms表单对象来获取提供者。 –
@HansPassant,我已经更新了上面的代码以反映我的'BackgroundWorker'的实现。 'SynchronizationContext'为null,但我不在Winform环境中,为此添加WinForm库会很诡异。这是一个COM/.NET库,它将向Excel中添加一些功能,但没有GUI。 – Adam