Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#在线程之间编组COM对象_C#_Multithreading_Com_Apartments - Fatal编程技术网

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

C#在线程之间编组COM对象,c#,multithreading,com,apartments,C#,Multithreading,Com,Apartments,我对C#marshal的COM对象是否存在于线程之间感到非常困惑。为此,我有一个应用程序,它以任务并行方式加载一组文件。我正在使用COM对象加载文件。加载COM对象后,我将该对象存储在一个中心列表中 然后,我尝试对这些数据执行一些处理,再次使用STATaskScheduler。然而在这一点上,我遇到了一个问题。我收到如下例外情况: An unhandled exception of type 'System.Runtime.InteropServices.InvalidComObjectExce

我对C#marshal的COM对象是否存在于线程之间感到非常困惑。为此,我有一个应用程序,它以任务并行方式加载一组文件。我正在使用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
[
    coclass,
    threading( apartment ),
    vi_progid( [Namespace.Class] ),
    progid( [Namespace.Class].6 ),
    version( 6.0 ),
    uuid( GUID_C[Class] ),
    helpstring( [Class]" Class" )
]
现在我的理解是,我收到这个错误是因为对象还没有被编组到新线程中。我以为这是C#为你做的事

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

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

编辑:COM对象定义如下:

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
[
    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的线程模型作为某种“有状态”逻辑的一部分,你的COM对象生活在
新的
边界上。如果是这种情况,请确保在同一
StaTaskScheduler
STA线程上创建和使用这些对象,而不在其外部。这样你就不用担心COM封送了。不用说,您应该只使用一个线程创建
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
的事件,请选中此项:


我只在
Marshal.ReleaseComObject
释放COM对象后,代码试图调用该对象时看到此错误。但我从未尝试在多个线程上使用STA线程COM对象,据我所知,这是行不通的。也就是说,您只能在创建COM对象的线程上使用该COM对象。此外,如果它被记录为STA线程,那么它应该在STA线程上使用。如果必须以这种方式使用该对象,我认为您需要添加线程同步:其他线程必须请求创建者线程调用COM对象。我看到此错误的次数是对从COM可调用包装器创建的实例调用
Marshal.ReleaseComObject
,然后尝试调用如果COM对象在注册表中正确声明了它们如何处理多线程(二者、单元等),则instance.COM(而不是.NET)上的方法将为您执行封送处理。如何声明您正在使用的对象?StaTaskScheduler造成的问题似乎比它解决的问题多得多。严格的规则是,拥有对象的线程必须保持活动状态才能使对象保持活动状态。使用StaTaskScheduler在UI线程上运行任务是一项毫无意义的工作。考虑让这些COM对象有一个可以继续运行的安全的家。@ HASPASANT:所以,如果它所创建的线程保持生存,那么COM将能够使它变成一个不同的线程?ID,而能够以某种方式在线程之间传递COM对象。类似于旧的Comarshall InterThreadInterfaceInStream…?我已经用少量的更多信息更新了我的问题@Goz,那么也许你根本不需要
StaTaskScheduler
。如果在MTA线程上创建STA COM对象,COM将创建隐式STA单元(用于该STA单元和其他类似STA对象),并将STA对象的代理封送到MTA客户端。这就是为什么它会像更新中所述那样工作。它可能会工作,但也可能很容易导致死锁,特别是当COM对象向MTA客户端发起一些事件或其他回调时。这里有一个简短而全面的崩溃过程:@ GOZ,如果您更喜欢使用COM封送处理,考虑使用全局接口表(Git)而不是<代码> COMARSHARTHEADTHELADIOFICANIONSWOR> /CODE >,这更简单。我这里有一个代码示例: