1

我试图了解 .NET 远程处理,试图在 .NET 中复制 VB6 ActiveX EXE。

到目前为止,我在所有客户端都可以共享的服务器上实例化了一个单例。

单例接受来自客户端的请求并验证数据,以事件的形式返回验证数据。这很好用——请求引用单例的类会触发它们的事件——即它们发送数据,接收经过验证的数据。

但是,我需要一个接口。客户端托管在 WPF 应用程序中(服务器也是如此),当它们接收数据时,我需要更新显示(文本框、列表框等)以反映客户端和单例之间的通信。

但是,一旦我添加了一个在主窗体中实现的事件供客户端在收到单例的回复后调用,我就会遇到运行时错误,抱怨主窗体没有序列化属性......

为了保持简洁,我将描述该过程如下

服务器运行代码:

            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
            //
            IDictionary myDictionary = new Hashtable();
            myDictionary["name"] = String.Format("PracticonChannel_{0}", Port);
            myDictionary["typeFilterLevel"] = TypeFilterLevel.Full;
            myDictionary["port"] = Port.ToString();
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;

            http = new HttpChannel(myDictionary, clientProvider, serverProvider);

            // Register RemotingShared.SingletonObject as a 
            // Singleton Server-Activated type.
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(Practicon.RemotingShared.UploadObjectSingleton), // Server-activated type
                "SingletonService",                     // objectUri
                WellKnownObjectMode.Singleton           // Singleton instancing mode
                );

            RemotingConfiguration.ApplicationName = " Upload Server";
            RemotingConfiguration.RegisterActivatedServiceType(
            typeof(Practicon.RemotingShared.UploadObjectSingleton));

客户端通过以下方式获取服务器激活的单例:

HttpChannel http1;
                // Set the formatters of the messages for delivery.
                BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
                BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
                //
                IDictionary myDictionary = new Hashtable();
                myDictionary["name"] = String.Format("PracticonChannel_{0}", Port);
                myDictionary["typeFilterLevel"] = TypeFilterLevel.Full;
                myDictionary["port"] = port.ToString();
                serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
                http1 = new HttpChannel(myDictionary, clientProvider, serverProvider);

                ChannelServices.RegisterChannel(http1, false);


                uploadObj= (UploadObjectSingleton)Activator.GetObject(
                            typeof(UploadObjectSingleton),
                            fullAddress);

//---------- Here's the problem...
                uploadObj.ReplyEvent += new UploadObjectReplyEventHandler(OnUploadReply);

OnUploadReply 是一个表单实现的事件,用于更新各种控件。当它在运行时分配时,由于主窗体缺少序列化属性而发生序列化异常。

这让我发疯了。有人可以向我展示/解释/告诉/讲道/讲授我如何更新用户界面以响应单例中触发的事件吗?

4

1 回答 1

1

好的,这个问题的答案是使用 WCF。它并不像听起来那么可怕,而且我的解决方案比我预期的要好。

我会向试图做我所面临的事情的人强调的是:

  1. 显然,创建一个服务器应用程序来托管并且只托管服务。我尝试做一些花哨的事情,例如使用服务器应用程序来维护服务的 UI——状态、它在做什么以及为/为谁。不!。只是不要。

  2. 仅在需要时保持客户端和服务器之间的连接打开。再长的时间,频道就有可能出现故障,经过数小时试图解决这个问题,试图从失败中恢复过来,你最好尝试编写有关如何放牧猫的说明。重新考虑你的问题。打开,使用,关闭。

  3. 无论如何,我必须想出一个替代具有 UI 的 ActiveX 控件。我创建了 3 个项目——服务器(用于托管)、客户端(用于为服务提供用户界面)和与服务交互的 COM 接口(称为函数、设置属性等)和外部应用程序。

COM 接口必须做的第一件事是尝试找到正在运行的服务器实例(顺便说一句,实现 WPF 应用程序的单个实例绝非易事,但这是题外话)

如果找不到,它会执行服务器应用程序,等待然后打开一个通道。每次 COM 接口必须对话/等待接口时都会重复此过程(显然,服务器应用程序只需要运行一次)。球痛,但这避免了可怕的“通道处于故障状态”综合症。以前,我会发现该服务可以托管,并且频道会在完全随机的时间内保持打开状态 - 1 分钟、一个小时、一天,但即使客户端/服务器什么都不做也会发生故障。由于我的服务正在控制北美(来自英国)的一条生产线,如果接口出现故障,直到它再次运行,我的首要任务是稳定。所以,到目前为止,“摇滚”和“硬”这两个词疯狂地浮现在脑海中

所以,重复,打开,使用,关闭。

希望这可以帮助。

毫米

顺便说一句,我赞成 Blam 的建议。

于 2013-12-19T21:29:17.623 回答