尽管 WCF 之前的版本今天仍然适用,但您可以使用一些 IPC 技术。
Pipes
Pipes就是这样一种技术。它是二进制的,在内核模式下运行并且速度非常快!虽然它的级别相当低并且确实not授予对“对象”的访问权限。
.NET 远程处理
.NET 远程处理将提供对对象的访问,但可能不如管道快。
管道和 .NET 远程处理都比序列化技术 WCF 更快,后者将内容转换为详细的 XML/SOAP。
COM
COM 是 IPC 的二进制协议。 COM 是一种客户端服务器模型,客户端从 COM 或 OLE 服务器请求数据。 COM 的美妙之处在于您拥有直接访问服务器中的对象 - 它们没有被序列化。例如请求 a 中的元素安全阵列 https://msdn.microsoft.com/en-us/library/windows/desktop/ms221482(v=vs.85).aspx.
A SAFEARRAY
是由类型安全数据组成的任意维度的自动化安全结构。幸运的是,.NET 将为我们隐藏 SAFEARRAY gobble-de-gook。
在我的示例中,我创建了一个Manager
将公开数组的类。为了到达Manager
我使用了工厂模式,这样Manager
本质上是一个单例。
您应该按如下方式布局您的项目:
-
MyComLib.Contracts.dll- 包含所有接口
-
MyComLib.dll- 包含实施
Factory
, Manager
首先是合同:
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IArrayItem
{
#region Properties
string Name { get; set; }
int Whatsit { get; set; }
#endregion
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IFactory
{
#region Methods
IManager CreateManager();
#endregion
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IManager
{
#region Properties
IArrayItem[] Array { get; }
#endregion
}
public static class MyComLibConstants
{
public const string FactoryProgId = "MickyD.MyComLib.Factory.1";
}
现在来说一下工厂模式:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof (IFactory))]
[Guid("...")]
[ProgId(MyComLibConstants.FactoryProgId)]
public class Factory : MarshalByRefObject, IFactory
{
#region IFactory Members
/// <summary>
/// Creates the manager.
/// </summary>
/// <returns></returns>
public IManager CreateManager()
{
return Manager.Instance;
}
#endregion
}
管理者:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof (IManager))]
[Guid("...")]
internal sealed class Manager : MarshalByRefObject, IManager
{
private static Manager _instance;
#region Constructor
/// <summary>
/// Prevents a default instance of the <see cref="Manager"/> class from being created.
/// </summary>
private Manager()
{
const int n = 5000;
Array = new IArrayItem[n];
for (int i = 0; i < n; i++)
{
Array[i]=new ArrayItem();
}
}
#endregion
#region Properties
/// <summary>
/// Gets the instance.
/// </summary>
/// <value>
/// The instance.
/// </value>
public static IManager Instance
{
get
{
if (_instance == null)
{
_instance = new Manager();
}
return _instance;
}
}
#endregion
#region IManager Members
/// <summary>
/// Gets the array.
/// </summary>
/// <value>
/// The array.
/// </value>
public IArrayItem[] Array { get; private set; }
#endregion
}
一个测试应用程序。这应该only参考MyComLib.Contracts.dll and 不是 MyComLib.dll.
class Program
{
static void Main(string[] args)
{
var type = Type.GetTypeFromProgID(MyComLibConstants.FactoryProgId);
var factory = Activator.CreateInstance(type) as IFactory;
var manager = factory.CreateManager();
var x = manager.Array[500].Whasit;
}
}
最后一步是改变这一点进行中COM 服务器到进程外COM 服务器,以便多个进程各自共享相同的内容Manager
并且不要创建自己的单例。换句话说,是跨进程的单例。当。。。的时候Manager
在运行时,它本质上是在它自己的进程空间中与所有其他客户端进程分开。
为此,您需要配置一个 COM 代理,详细解释如下here http://dotnet.dzone.com/articles/hosting-net-dll-out-process.
文件映射/共享内存
最后,文件映射允许您操作文件,就好像它只不过是进程地址空间中的一大块内存一样。无需繁琐的文件查找;读/写操作。只需获取指向内存块的指针并开始读/写。系统将完成剩下的工作。
MSDN:
您可以使用文件映射的特殊情况在进程之间提供命名共享内存。如果在创建文件映射对象时指定系统交换文件,则文件映射对象将被视为共享内存块。其他进程可以通过打开同一文件映射对象来访问同一内存块。告诉我更多 https://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx#base.using_a_file_mapping_for_ipc
遗憾的是,它仍然需要您首先写入数据,并且为了使其最有效,您需要更改应用程序以将内存块视为事实来源,而不是内存中的数组。否则你将一直在序列化。
然而,通过交换文件共享内存在技术上确实允许您消除客户端-服务器应用程序之间的任何序列化-反序列化以及“堆上”的数据重复。尽管正如我所说,您可能需要调整您的应用程序以使用原始内存缓冲区而不是对象。
告诉我更多
- .NET Framework 中的管道操作 https://msdn.microsoft.com/en-us/library/bb762927(v=vs.110).aspx
- .NET 远程处理 https://msdn.microsoft.com/en-us/library/vstudio/72x4h507(v=vs.100).aspx
- 进程间通信 https://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx#base.using_com_for_ipc
NOTE:与普遍看法相反,.NET Remotingis not完全obsolete。它的当代用途之一是不同环境中的对象之间的通信AppDomains
在同一流程中,您通常会做的事情plug-in systems
.