我有一个需要关注事物的进程外COM服务器。此服务器作为服务运行,并且在内部是单例。为简单起见,我会称他为BossCom。
我有另一个进程外COM服务器,它是一个工作者。对于系统稳定性而言,它是一次性服务器(意味着如果您创建2个WorkerCom,则有2个WorkerCom.exe正在运行)。为简单起见,我会称他为WorkerCom。
WorkerCom可以通过任何东西启动,即使有人通过命令行使用正确的命令行参数运行它也可以自己启动。
总体目标是让BossCom知道WorkerComs是什么,知道他们在做什么,并能够给他们订单(暂停,停止,加速等)。
我最初的想法是,每当WorkerCom启动时,他都会CoCreateInstance一个BossCom并调用BossCom-> RegisterWorker(IUnknown me)。然后当WorkerCom即将关闭时,他会打电话给BossCom-> UnregisterWorker(IUnknown me)。 BossCom可以为IWorkerCom查询IUnknown,并能够发出命令。
如果所有这些com对象都在同一个进程中,那将会很有效,但事实并非如此。我想过使用GlobalInterfaceTable,但它只是一个单一过程意义上的全局。
我花了几天时间研究这个并且不知所措。也许我是隧道视野。
如何编组从工人到老板的com对象的引用?
哦,而且,对于它的价值,BossCom是用C#编写的,而WorkerCom是用ATL C ++编写的,但我会用VB,Scala,Lisp或其他任何东西编写解决方案。我想我可以翻译核心理念。 : - )
答案 0 :(得分:2)
您应该查看Monikers,用于识别COM对象实例,甚至跨越不同的计算机。
答案 1 :(得分:2)
根据评论,这确实是开箱即用的。有一个额外的细节,但它使它工作。
最初当我在查看处理复制接口的C#接口时,参数类型是IntPtr。好吧,IntPtr只是一个很长的时间,所以它按原样传输值,因此不起作用。
关键是在参数上设置MarshalAs属性。所以我的RegisterWorker方法如下所示:
public void RegisterWorker(
[In, MarshalAs(UnmanagedType.IUnknown)] object ptr
)
{
IWorkerCom worker = (IWorkerCom) ptr;
Workers.Add(worker);
}
非常棒。
答案 2 :(得分:1)
最近我不得不做类似的事情,发现使用共享内存对我来说非常好。 BossCom可以创建和拥有共享内存,工作人员可以通过在共享内存中输入来注册。这是我所说的MSDN link。请记住使用互斥锁来同步对内存的访问...
答案 3 :(得分:1)
您在C#中创建可编组接口的能力有限。没有简单的方法来设置代理。在ATL中没有这样的问题,在IDL中声明一个回调接口。并使用RegisterWorker()调用传递实例指针。服务器应该存储它,直到它获得取消注册。使用该回调接口生成通知。
答案 4 :(得分:0)
您还应该查看ROT(运行对象表),它可能是解决此问题的另一种方法。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms695276(v=vs.85).aspx