gpt4 book ai didi

C# 在线程之间编码 COM 对象

转载 作者:行者123 更新时间:2023-11-30 16:11:04 24 4
gpt4 key购买 nike

我对 C# marshal 的 COM 对象是否在线程之间感到非常困惑。为此,我有一个应用程序正在以任务并行方式加载一组文件。我正在使用 StaTaskScehduler使用 COM 对象加载文件。加载 COM 对象后,我将该对象存储在中央列表中。

稍后我尝试再次使用 STATaskScheduler 对该数据执行一些处理。但是在这一点上我遇到了问题。我收到如下异常:

An unhandled exception of type 'System.Runtime.InteropServices.InvalidComObjectException' occurred in MadCat.exe

Additional information: COM object that has been separated from its underlying RCW cannot be used

现在我的理解是我收到此错误是因为该对象尚未编码到新线程中。我以为这是 C# 为您做的事情?

如何在一个线程中创建单元线程 COM 对象,然后在另一个线程中使用它?

我是不是找错人了?我什至不应该为我的线程使用 Sta 公寓吗?我可以保证永远不会同时从多个线程访问该对象。非常感谢任何想法。

编辑:COM对象定义如下:

[
coclass,
threading( apartment ),
vi_progid( [Namespace.Class] ),
progid( [Namespace.Class].6 ),
version( 6.0 ),
uuid( GUID_C[Class] ),
helpstring( [Class]" Class" )
]

所以根据我的理解,这是一个单元线程对象,对吧?我刚刚尝试使用不设置单元状态(默认为 MTA?)的修改后的任务调度程序。当我在一个线程中创建它并从另一个线程使用它时,这个对象似乎确实起作用了。这是安全的还是它会以其他方式回来咬我?

COM 的线程模型总是把我搞糊涂了:/

最佳答案

看来您正在使用 Stephen Toub 的 StaTaskScheduler作为某些“有状态”逻辑的一部分,您的 COM 对象跨越 StartNew 边界存在。如果是这种情况,请确保在同一个 StaTaskScheduler STA 线程上创建和使用这些对象,而不是在它之外的任何地方。那么您根本不必担心 COM 编码(marshal)处理。不用说,您应该创建只有一个线程的 StaTaskScheduler,即 numberOfThreads:1

我的意思是:

var sta = new StaTaskScheduler(numberOfThreads:1);

var comObjects = new { Obj = (ComObject)null };

Task.Factory.StartNew(() =>
{
// create COM object
comObjects.Obj = (ComObject)Activator.CreateInstance(
Type.GetTypeFromProgID("Client.ProgID"));
}, CancellationToken.None, TaskCreationOptions.None, sta);

//...

for(int i=0; i<10; i++)
{
var result = await Task.Factory.StartNew(() =>
{
// use COM object
return comObjects.Obj.Method();
}, CancellationToken.None, TaskCreationOptions.None, sta);
}

如果 Obj.Method() 返回另一个 COM 对象,您应该将结果保存在同一个 StaTaskScheduler 的“公寓”中并从那里访问它:

var comObjects = new { Obj = (ComObject)null, Obj2 = (AnotherComObject)null };
//...
await Task.Factory.StartNew(() =>
{
// use COM object
comObjects.Obj2 = comObjects.Obj.Method();
}, CancellationToken.None, TaskCreationOptions.None, sta);

如果您还需要处理源自 Obj 的事件,请检查:

关于C# 在线程之间编码 COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24780314/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com