WPF 从零开始开发 dotnet Remoting 程序

本文告诉大家如何不使用框架,从零开始开发一个 dotnet remoting 程序

在我的另一篇博客 WPF 使用RPC调用其他进程 就大概告诉了大家如何在 WPF 使用 dotnet remoting 但是这篇博客是从大的方向告诉大家,所以本文就从代码上告诉大家如何写一个 dotnet remoting 做多进程框架。

首先需要创建几个项目,下面就是本文创建的项目

  • Native WPF 程序
  • Remote 控制台项目
  • RemoteObject 类库

引用项目

这里几个项目的应用关系是 Native 引用 Remote 和 RemoteObject 。在 Remote 项目引用 RemoteObject 项目。

这里的 Native 项目就是本地的 WPF 程序,而 Remote 控制台项目就是远程的进程,本文让 Native 作为主进程,让 Remote 进程做远程。

这里的 RemoteObject 就是放一些在 Native 和 Remote 都需要使用的类。

通过每个项目的用法就可以知道引用,因为我需要从 Native 启动 Remote ,在 VisualStudio 只要引用一个项目就可以让这个项目输出到项目所在的输出文件,所以就可以快速找到 Remote 进程。

现在尝试创建三个不同的项目,然后编译一下,这时就可以从 Native 的输出文件夹看到下面的文件

启动软件

在 Native 启动 Remote 很简单,因为在相同的文件夹,所以使用下面的代码启动

因为 Remote 只是一个控制台项目,为了让用户可以看到 Remote 就需要在主函数添加一些代码

        static void Main(string[] args)
        {
            Console.WriteLine("启动远程应用");

            while (true)
            {
                Console.Read();
            }
        }

然后在 Native 的主页面添加下面代码

        public MainWindow()
        {
            InitializeComponent();

            var processStartInfo = new ProcessStartInfo(ProgressName);
            Process.Start(processStartInfo);
        }

        private const string ProgressName = "Remote.exe";

现在运行一下 Native 就可以看到 Remote 也运行

注册类

现在尝试在远程 Remote 注册一个类,然后在本地调用 Remote 的这个类

先创建一个类请看代码

    [Serializable]
    public class Addition : MarshalByRefObject
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }

这个类先放在 RemoteObject 这样就可以在 Native 和远程都知道这个类

注册一个类的方法有很多个,本文只告诉大家通过 RemotingServices.Marshal 的方式注册

因为在 Remote 的主函数是等待输入也就是这个线程是无法使用,所以需要新创建一个线程

        static void Main(string[] args)
        {
            Console.WriteLine("启动远程应用");

            var thread = new Thread(() =>
            {
                var addition = new Addition();
                RemotingServices.Marshal(addition, "add");
            })
            {
                IsBackground = true,
            };

            thread.Start();

            while (true)
            {
                Console.Read();
            }
        }

现在就通过 RemotingServices.Marshal 注册了 Addition 类。

添加通道

为了让 Native 可以访问到 Remote 就需要 Remote 添加 Channel 让 Native 访问

在添加通道之前需要添加 .Net Remoting 的引用,右击三个项目添加引用,选择 System.Runtime.RemotingSystem.Runtime.Serialization 第一个就是基础支持第二个是用来序列化

使用下面的代码创建 TCPChannel 传入的参数就是端口

        private static IChannel CreatChannel()
        {
            var tcpServerChannel = new TcpServerChannel(8086);
            return tcpServerChannel;
        }

在传入的时候需要本地不存在冲突端口,也就是现在的端口没有被其他程序使用

通过这个方法就可以创建,创建之后需要注册,使用 ChannelServices.RegisterChannel 方法就可以注册,这个方法第二个参数是要不要使用安全传输

        static void Main(string[] args)
        {
            Console.WriteLine("启动远程应用");

            var thread = new Thread(() =>
            {
                var addition = new Addition();
                RemotingServices.Marshal(addition, "add");

                _channel = CreatChannel();
                ChannelServices.RegisterChannel(_channel, false);
            })
            {
                IsBackground = true,
            };

            thread.Start();

            while (true)
            {
                Console.Read();
            }
        }

        private static IChannel _channel;

        private static IChannel CreatChannel()
        {
            var tcpServerChannel = new TcpServerChannel(8086);
            return tcpServerChannel;
        }

现在就在 Remote 的准备完成了

在 Native 也需要注册通道才可以和 Remote 通信,在 Native 注册的 TCPChannel 是使用 TcpClientChannel 类,请看代码

        public MainWindow()
        {
            InitializeComponent();

            var processStartInfo = new ProcessStartInfo(ProgressName);
            Process.Start(processStartInfo);

            var tcpClientChannel = new TcpClientChannel();
            ChannelServices.RegisterChannel(tcpClientChannel, false);

        }

现在就注册完成了,下面就是从 Native 调用远程的类

调用方法

在 Native 的界面添加一个按钮,在按钮按下的时候就触发 Remote 的类的函数

这里关于在 Native 的界面添加按钮和按钮事件本文就不说了,因为很简单。

在按钮按下的代码使用 Activator.GetObject 方法拿到远程的类

        private void Button_OnClick(object sender, RoutedEventArgs e)
        {
            var addition = (Addition) Activator.GetObject(typeof(Addition), "tcp://localhost:8086/add");
            Debug.WriteLine(addition.Add(1, 2));
        }

这里通过 8086 端口拿到刚才注册的 Addition 类,需要重新告诉大家 Addition 是如何注册的

                RemotingServices.Marshal(addition, "add");

在 RemotingServices 的 Marshal 第一个参数就是需要注册的类,第二个就是拿到这个类的链接

所以通过 tcp://localhost:8086/add 就可以拿到远程的类

现在点击按钮就可以看到输出 3 为了让大家知道是调用远程的方法,在 Addition 类添加输出

        public int Add(int a, int b)
        {
            Console.WriteLine("   调用加法");
            return a + b;
        }

现在在 Native 按下按钮就可以看到 Native 的 VisualStudio 输出 3 同时 Remote 控制台输出 调用加法

上面就是最简单的使用 dotnet remoting 的例子,在接下来将会分为不同的细节来写很多篇博客。

先回忆一下,创建一个 .Net Remoting 需要经过哪些步骤

  1. 让 Native 引用 Remote 这样就可以让 Native 启动 Remote
  2. Remote 启动之后需要注册类,也就是给 Native 使用的类需要先注册
  3. 为了让 Native 和 Remote 通信就需要注册通信
  4. 通过 Activator.GetObject 拿到 Remote 的类返回透明代理
  5. 在 Native 通过 透明代理调用 Remote 的方法

在这个过程中几乎所有步骤都可以拿出来说

如果不想了解太多细节,想快速使用,请看WPF 封装 dotnet remoting 调用其他进程

参见:

Microsoft .Net Remoting系列专题之三:Remoting事件处理全接触 - 张逸 - 博客园

Microsoft .Net Remoting系列专题之二:Marshal、Disconnect与生命周期以及跟踪服务 - 张逸 - 博客园

In Depth .NET Remoting

Ingo Rammer,《Advanced .NET Remoting》

.net remoting 抛出异常

《Professional C#》 第3版

.NET Remoting程序开发入门篇-博客-云栖社区-阿里云

.NET Remoting中的事件处理(.NET Framework 2.0)(一) - 大坏蛋 - 博客园

WPF 使用RPC调用其他进程


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码生

实现更安全、高扩展的自定义键盘 非UIButton

自定义键盘的封装网上的例子比比皆是,有的封装的非常完美,直接pod 集成到项目中便可以简单的使用,可是为什么我还要自定义一个呢? 一不是不是为了显摆,二不是网...

12420
来自专栏c#开发者

Visual Studio 2005 IDE 技巧和窍门

Visual Studio 2005 IDE 技巧和窍门 发布日期: 2007-02-26 | 更新日期: 2007-02-26 James Lau Micro...

30440
来自专栏小白课代表

PDF的最简单处理方案之一。

10620
来自专栏bboysoul

esxi6.5 安装omsa(OpenManage Server Administrator)

OMSA(OpenManage Server Administrator)是Dell主机的硬件检测和维护软件,可以安装在windows,linux还有esxi中...

22040
来自专栏GopherCoder

Python 强化训练:第十篇

18030
来自专栏LIN_ZONE

谷歌断点调试(转载)

简单地说,断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,...

15240
来自专栏向治洪

React native开发中常见的错误

react native环境搭建请移步:react native环境搭建 这里说说react native创建完成之后,运行中出现的常见问题, 问题1: jav...

33760
来自专栏张戈的专栏

桌面白屏(Active故障)修复批处理

一年前我在做用户系统维护服务工作时发现 AD 域环境下,AD 用户桌面经常会出现壁纸无法显示,ActiveDesktop 桌面损坏之类的故障,当时从前人心得里学...

34060
来自专栏自动化测试实战

《selenium2 python 自动化测试实战》(12)——跳过验证码登录add_cookie

54750
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(82)-Easyui Datagrid批量操作(编辑,删除,添加)

前言 有时候我们的后台系统表单比较复杂,做过进销存或者一些销售订单的都应该有过感觉 虽然Easyui Datagrid提供了行内编辑,但是不够灵活,但是我...

53150

扫码关注云+社区

领取腾讯云代金券