在使用事件进行远程处理期间更新GUI

时间:2013-11-08 15:07:23

标签: c# .net singleton .net-remoting

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

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

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

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

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

为了保持这种简洁,我将按如下方式描述该过程

服务器使用代码运行:

            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是一个Form实现的事件,用于更新各种控件。在运行时分配时,由于主窗体缺少序列化属性,会发生序列化异常。

这让我疯了。有人可以向我展示/解释/讲述/讲道/讲授我如何更新用户界面以响应在单身内发射的事件吗?

1 个答案:

答案 0 :(得分:1)

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

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

  1. 显然,创建一个服务器应用程序来托管AND ONLY HOST服务。我尝试过做一些奇特的事情,例如使用服务器应用来维护服务的用户界面 - 状态,它正在做什么以及为谁/为谁。别!。不要。

  2. 只有在需要时才打开客户端和服务器之间的连接。任何更长的时间和渠道都有发生故障的风险,经过几个小时试图解决这个问题,试图从失败中恢复过来,你最好试着写一些关于如何对猫群的说明。重新思考你的问题。打开,使用,关闭。

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

  4. COM接口必须做的第一件事就是尝试查找服务器的运行实例(顺便说一句,实现WPF应用程序的单个实例绝非易事,但这不是主题)

    如果找不到,则执行Server应用程序,等待然后打开一个频道。每次COM接口必须通话/等待接口时,都会重复此过程(显然,Server应用程序只需运行一次)。一个球疼,但这避免了可怕的'通道处于故障状态'综合征。以前,我会发现该服务可以托管,并且一个频道保持开放一段时间 - 一分钟,一小时,一天,但即使客户端/服务器什么都不做,也会发生错误。由于我的服务是控制北美(来自英国)的生产线,如果界面发生故障,NOTHING会再次运行,我的优先事项是稳定性。因此,“摇滚”和“艰难”这些词语令人不可思议地浮现在脑海中

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

    希望这有帮助。

    MM

    BTW我对Blam的建议表示赞同。