COM Interop RCW痛苦 [英] COM Interop RCW agony

查看:61
本文介绍了COM Interop RCW痛苦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很困惑我应该或不应该在不同情况下调用COM对象上的Marshal.ReleaseComObject()。所以我尝试使用以下示例代码来说明:



I got quite confused about when I should or should not call Marshal.ReleaseComObject() on a COM object in different situations. So I try to used the following sample codes to illustrate:

// suppose the following classes are 3rd-party COM Interop classes:
class comProducer;
class comConsumer1;
class comConsumer2;
class comData;


private List<comData> lstCon1;  // data-input for comsumer1_thread
private List<comData> lstCon2;  // data-input for consumer2_thread


// in producer thread, fetch data and pass it to different consumer threads in regular basis:
void producer_thread()
{
  comProducer producer = new comProducer();
  
  while (!stop) {
    comData data;
    producer.get(out data);

    // ... omit any code for sync and locking 

    lstCon1.Add(data);  // ... signal comsumer1_thread for processing
    lstCon2.Add(data);  // ... signal comsumer2_thread for processing

    Marshal.ReleaseComObject(data);  // (a)

    Sleep(100);
  }// while

  Marshal.ReleaseComObject(producer);
}

void comsumer1_thread()
{
  comConsumer1 con1 = new comConsumer1();

  while (!stop) {
    // ... omit any code for locking and sync ...
    foreach (comData data in lstCon1) {
      con1.process(data);
      Marshal.ReleaseComObject(data);  // (b)
    }
    lstCon1.Clear();
  }// while

  Marshal.ReleaseComObject(con1);
}

void comsumer2_thread()
{
  comConsumer2 con2 = new comConsumer2();

  // comConsumer2 also exposes other interfaces:
  comIfaceA ifA = con2;
  comIfaceB ifB = (comIfaceB)con2; // this one requires explicit casting

  List<comData> local_list = new List<comData>();
  while (!stop) {
    // ... again, omit any code for locking and sync ...

    // move all data from lstCon2 to local_list:
    local_list.Insert(0, lstCon2);
    lstCon2.Clear();  // (c)

    foreach (comData data in local_list) {
      con2.process(data);
      Marshal.ReleaseComObject(data);  // (d)
    }
    local_list.Clear();
  }// while

  Marshal.ReleaseComObject(ifA); ifA = null;   // (e)
  Marshal.ReleaseComObject(ifB); ifB = null;   // (f)
  Marshal.ReleaseComObject(con2); con2 = null; // (g)
}

步骤(a)〜(g)是否正确完成?

Are the steps (a) ~ (g) correctly done?

当COM对象被插入到通用容器中时(例如List< T> .Add()),该COM对象的RCW /引用计数是否会自动增加?类似地,如果从通用容器中删除该COM对象,或者甚至只是将
指定为null(例如data = null),COM对象RCW / ref计数是否会自动递减?

When a COM object is being inserted into a generic container (e.g. List<T>.Add()), does the RCW/reference count of that COM object incremented automatically? Similarly, if that COM object is being removed from a generic container, or even just being assigned to null (e.g. data = null), will the COM objects RCW/ref count automatically decremented?

我不知道如何清楚地了解这一点。如上面的代码所示,如​​果一个COM对象被不同的位置/线程共享,我必须清楚地知道何时调用Marshal.ReleaseComObject()以确保共享的COM对象一旦被销毁就会被破坏
不再需要,无需等待GC声明它。

I somehow don't get a clear picture of that. As illustrated in the above code, if a COM object is being shared by different locations/threads, I have to know clearly WHEN to call Marshal.ReleaseComObject() to ensure that the shared COM object will be destroyed once it is no longer needed, without waiting for GC to claim it.

并且,任何CComPtr< T>和CAdapt< T> C#的等价?

And, any CComPtr<T> and CAdapt<T> equivalence for C#?

推荐答案

嗨s.tf,

感谢您在此发帖。

>> 我很困惑我什么时候应该或不应该在
不同情况下调用COM对象上的Marshal.ReleaseComObject()。

Marshal.ReleaseComObject方法( Object) 用于显式控制从托管代码使用的COM对象的生命周期。

Marshal.ReleaseComObject Method (Object) is used to explicitly control the lifetime of a COM object used from managed code.

此方法使您可以强制RCW引用计数释放,以便在您需要时准确发生它来。但是,不恰当地使用ReleaseComObject可能会导致应用程序失败,或者可能导致访问冲突。

This method enables you to force an RCW reference count release so that it occurs precisely when you want it to. However, improper use of ReleaseComObject may cause your application to fail, or may cause an access violation.

考虑应用程序域中的托管代码保留在代表COM组件。如果在RCW上调用ReleaseComObject方法,托管代码将无法访问RCW并将引发InvalidComObjectException
异常。

Consider a scenario in which managed code in an application domain is holding onto an RCW that represents a COM component. If you call the ReleaseComObject method on the RCW, the managed code will be unable to access the RCW and will raise an InvalidComObjectException exception.

因此,仅在使用ReleaseComObject时才使用它是绝对必要的。如果要调用此方法以确保在确定的时间释放COM组件,请考虑使用FinalReleaseComObject方法。 

Therefore, use the ReleaseComObject only if it is absolutely required. If you want to call this method to ensure that a COM component is released at a determined time, consider using the FinalReleaseComObject method instead. 

有关详细信息,请参阅MSDN文章。

For more details, please refer t the MSDN article.

https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject(v = vs.110).aspx

>> 当COM对象被插入到通用容器中时(例如List< T> .Add()),
确实如此该COM对象的RCW /引用计数自动递增? 


>>When a COM object is being inserted into a generic container (e.g. List<T>.Add()), does the RCW/reference count of that COM object incremented automatically? 

运行时只创建一个每个COM对象的RCW,无论该obj上存在多少引用ect。 

The runtime creates exactly one RCW for each COM object, regardless of the number of references that exist on that object. 

有关详细信息,请参阅MSDN文章。

For more details, please refer to the MSDN article.

https://docs.microsoft.com/en-us/dotnet/framework/interop/runtime-callable-wrapper

最好的问候,

Wendy


这篇关于COM Interop RCW痛苦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆