wcf 创建 寄宿在winform_wcf寄宿到winform实例 - CSDN
精华内容
参与话题
  • 之前学习老A博客和《WCF全面解析》时最常用到的是控制台寄宿,近期由于项目需求,需要在WinForm程序中调用WCF服务,本博文通过一个简单的实例来演示WCF在WinForm中的寄宿。并着重介绍如何利用事件绑定控制宿主主UI...

    背景:

    WCF服务需要寄宿到相应的可运行进程中执行,常见的有四种寄宿,分别是控制台程序、WinForm程序、IIS和Windows服务。之前学习老A博客和《WCF全面解析》时最常用到的是控制台寄宿,近期由于项目需求,需要在WinForm程序中调用WCF服务,本博文通过一个简单的实例来演示WCF在WinForm中的寄宿。并着重介绍如何利用事件绑定控制宿主主UI界面控件。

    题记:

    之前一直坚守在C++阵地,对于新语言、新技术(诸如Python、J2EE、Bigdata、AI)不甚感冒。自以为“原理”都是想通的,无非就是语法略有不同、集成的API数量级不同而已,想以不变应万变。——归根结底,这是一种精神上的懒惰与懦弱,尤其当从Student Context切换到Working Context后,倍感担忧。大脑能分配给每个任务的时间片越来越短,却无法切换到多CPU/多核模式,加之‘年老体衰’,‘内存’脑容量越来越少,汗Σ( ° △ °|||)︴啊。
    穷途末路,遂求变革。开始写写技术博客,将已有知识转存到其他介质以弥补内存日渐不足;浏览学习新技术,提升新技能,弥补这台老CPU效率。
    书归正传,之前很少用C/C++开发网络式、分布式应用,大多停留在C/S层面。因此在互联网+时代早已落伍,遂借着工作和兴趣,开始涉猎WCF和J2EE,顿时觉得好高大上,兴趣盎然,不过WCF(或J2EE)都是之前技术体系的集大成者,学习曲线及其陡峭,啃了半个月的书本却总感觉闷闷的,不敞亮,还需加把劲,再接再厉。
    下面就简单记录一下初次学习WCF的体会,文中会给出一个WCF实例,实例模拟的应用场景是:

    两个WinForm终端A和B,A中寄宿一项WCF服务,B中调用该服务向A发送指令消息,并在A的界面中显示(其实类似于QQ聊天)

    结构示意图如下:
    这里写图片描述

    WCF简介:

    微软从.NET3.0开始引入了WPF、WCF和WF三模块。
    这里写图片描述

    WPF,Windows Presentation Foundation是微软用于Windows的同一显示子系统,由显示引擎和托管代码框架组成。Windows Presentation Foundation 统一了 Windows 创建、显示和操作文档、媒体和用户界面 (UI) 的方式,使开发人员和设计人员可以创建更好的视觉效果、不同的用户体验。
    WCF,Windows Communication Foundation 是微软为构建面向服务的应用提供的分布式通信编程框架。使用该框架,开发人员可以构建跨平台、安全、可靠和支持事务处理的企业级互联应用解决方案。
    WF,Windows Workflow Foundation是一个通用的编程框架,它可用于创建需要对外部实体的信号作出响应的交互式程序。交互式程序的基本特征是它会在执行期间暂停某一长短未知的时段,以等待输入。

    本博文主要用到的是上述三种新特性中的WCF,即分布式通信框架。Windows Communication Foundation,WCF,是微软开发的构建面向服务应用的统一编程模型,一种框架。WCF是一个运行时环境和一套API,用于创建在服务与客户端间传递消息的新系统。
    WCF是基于消息的,任何东西都可以被当做是消息在编程模型中统一处理。消息在终结点间传递。终结点(Endpoints)是消息发送或消息接收(或者发送与接收)的地方。利用WCF,可以将数据以异步消息的方式从一个服务终结点发送到另一个。消息可以是多种多样,简到XML格式的一个字符或一个单词,繁至二进制数据流。

    由于刚刚涉猎,博文中就不过多介绍WCF的细节了,自己也没搞懂吃透。有兴趣可以浏览WCF大神的博客专栏 。从一个初学者不成熟的角度来看,

    【拙见1】:WCF是一种框架,最简单的情境中只要你在两端(服务端和客户端)做好约定(契约),通过WCF绑定就可以让两端进行相互调用,无论两者是否在同一进程、是否在同一主机、是否在同一平台,WCF技术使得跨进程、跨平台可以悄无声息。

    【拙见2】:姑且这么认为,WCF大大减少了程序员在底层交互上的工作,只需要关注业务层的逻辑即可。大大减少了程序部署的难度,使得应用普适性更强。

    WCF寄宿:

    直接以实例来讲解吧,操纵系统运行和分配资源的最小单位是进程。然而在WCF开发过程中,往往会将Contract(契约,或者说是约定)、Service(契约具体实现)分别以库的形式发布,因此在实际应用中要想使用WCF服务,需要将对应WCF库寄宿到可执行环境中,常见的有四种方式——控制台程序、Winform程序、IIS和Windows Service。这里按照博文之前的使用场景,使用Winform程序寄宿WCF服务,并给出具体的实例,其他方式的介绍可参考老A的博客

    WinFrom4HostWCFService:

    WCF契约:

    从编程角度来看,契约(Contracts)就是WCF框架中用于制定服务的统一标准,就是一些接口。
    【注】:这种说法不够精确,严格的说ServiceContract是一堆接口;而在接口的相关约束、配置中需要其他契约的配合,诸如接口中具体函数需要使用OperationContract、函数的具体参数需要DataContract、函数体内的异常和错误需要FaultContract,除此以外还有具体交互过程中使用的MessageContract。

    为了简单起见,姑且认为契约就是用于约束接口的相关规定吧。本文为了简单起见,设想服务端提供的服务是“收到Winform客户端发送的消息,直接在服务端主窗口中利用MessageBox以消息窗口形式显示出来。这里需要注意的是此处建立的WCF契约类是传统的C#类库,在该类库中如何才能在接收到客户端发送的请求后,主动触发主UI界面进行弹窗消息提示呢?这里就要涉及到C#的规定,对于Winform工程只有创建控件的主UI线程才能对其操作。那我们该如何实现呢?搜索了部分资料后发现,在WCF的契约服务类中可以使用通常的事件绑定。具体代码如下:
    【–服务契约类–】

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    
    namespace WCF.WcfContract
    {
    [ServiceContract(Name="WcfNotify")]
    public interface INotify2WinForm
    {
    [OperationContract]
    void Notify2WinForm(string message);
    }
    }
    


    【–服务契约实现类–】

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using WCF.WcfContract;
    using System.ServiceModel;
    namespace WCF.WcfService
    {
    public delegate void DisplayMessage(string mes);
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class NotifyService:INotify2WinForm
    {
    public DisplayMessage displayMessage;
    public void Notify2WinForm(string message)
    {
    if (!string.IsNullOrWhiteSpace(message))
    {
    if (null != displayMessage)
    displayMessage(message);
    }
    }
    }
    }
    


    【注1】:在建立Contract和Service具体实现类时需要在工程中添加System.ServiceModel引用
    【注2】: ServiceContract必须添加InstanceContextMode=InstanceContextMode.Single设置,否则无法正常启动WCF服务

    WCF寄宿:

    寄宿就是建立一种可执行环境,然后调用WCF服务类库,即DLL动态库。这里我们建立的是Windows窗体应用程序,即Winform程序。程序界面中只有两个按钮,用于启动和关闭WCF服务。界面如下所示:
    这里写图片描述
    这里采用代码方式来实现WCF服务,具体的实现代码如下所示:

    NotifyService wcfService = new NotifyService();
    wcfService.displayMessage = this.DisplayMessage;
    host = new ServiceHost(wcfService);
    WSHttpBinding httpBinding = new WSHttpBinding(SecurityMode.None);
    host.AddServiceEndpoint(typeof(INotify2WinForm), httpBinding, "http://localhost:8900");
    NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.None);
    host.AddServiceEndpoint(typeof(INotify2WinForm), tcpBinding, "net.tcp://localhost:1700/");
    host.Open();
    


    WCF客户端:

    为了演示方便,并未使用SvcUtil.exe来添加WCF服务,直接在客户端工程中添加服务契约工程的引用。然后在主程序中直接使用Coding的方式创建信道调用WCF服务,具体代码如下:

    EndpointAddress edpHttp = new EndpointAddress("http://localhost:8900/");
    EndpointAddress edpTcp = new EndpointAddress("net.tcp://localhost:1700/");
    
    WSHttpBinding httpBinding = new WSHttpBinding(SecurityMode.None);
    ChannelFactory<INotify2WinForm> factory = new ChannelFactory<INotify2WinForm>(httpBinding);
    INotify2WinForm channel = factory.CreateChannel(edpHttp);
    
    channel.Notify2WinForm("WinForm4WCFTest-zssure");
    ((IClientChannel)channel).Close();
    

    总结:

    实际测试结果如下,先启动WCF宿主程序WinForm4HostWCF,单击“启动WCF”按钮后;启动客户端WinformClient4WcfTest。在窗口中输入任意字符串,例如zssure test WCF 2015/04/04,单击“testWCF”按钮后,会看到WinForm4HostWCF界面弹出消息窗口,显示zssure test WCF 2015/04/04。具体结果图如下:
    这里写图片描述

    【ZSSURE】:

    此次演示过程中会发生众多其他错误,比如在WinForm4HostWCF窗口的MessageBox未关闭的情况下,客户端再次单击“testWCF”时服务端无法响应,且界面会卡死如果长时间未关闭MessageBox窗口,会弹出超时响应的错误窗口。这说明WCF框架其底层的机制很繁琐,虽然上手容易但是要想开发出稳定的、适于具体场景的应用需要具有丰富的实战经验,再接再厉还需继续努力,有时间会对上述两个错误进行详细分析。敬请期待……

    【源码下载】:

    【GitHub】: 源代码下载 【注】:近期Github受到攻击,上传可能会有延时,请耐心等待……
    【CSDN】: 源代码下载




    作者:zssure@163.com
    时间:2015-04-04

    展开全文
  • wcf学习--建立最简单的WCF服务

    万次阅读 多人点赞 2012-09-18 16:19:31
    VS2010里建立一个最简单的WCF服务,基本流程如下:   一:新建WCF应用 首先,新建一个WCF服务的应用(这里以framework 4.0为例),如下图所示,   建立完成之后,VS将自动生成一个最简单的WCF工程,...
    在VS2010里建立一个最简单的WCF服务,基本流程如下:
     
    一:新建WCF应用
    首先,新建一个WCF服务的应用(这里以framework 4.0为例),如下图所示,

     
    建立完成之后,VS将自动生成一个最简单的WCF工程,在这个应用中,包含了最基本“契约(Contract)”以及“服务功能实现(Service)”.
    工程如下:


    不需要编辑任何文件,直接编译生成,得到一个WcfService1.dll文件
     
    二、WCF应用中的契约(Contract)
    在生成的WCF工程中,IService1.cs中为“契约(Contract)”(本例中契约和服务放在同一个工程下了,实际上也可以分为两个工程),代码如下:
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);
        
        [Operation Contract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
    // TODO: Add your service operations here
    }
     
    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";
        [DataMember]
        public bool BoolValue
        {
            get {return boolValue; }
            set {boolValue = value; }
        }
     
        [DataMember]
        public string StringValue
        {
            get {return stringValue; }
            set {string Value = value; }
        }
    }


     
    可以看到,声明了服务契约IService1,以接口形式声明,其中还包括两个操作契约GetData以及GetDataUsingDataContract。还声明了数据契约CompositeType,以类的形式声明,包含两个数据成员BoolValue和StringValue。
     
    三、WCF应用中的服务功能实现(ServiceBehavior)
    在生成的WCF应用中,Service1.svc.cs中为“服务功能实现(ServiceBehavior)”(本例中契约和服务放在同一个工程下了,实际上也可以分为两个工程),代码如下(Service1.svc还有其它作用,后面再说):
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}",value);
        }
     
        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite== null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue+= "Suffix";
            }
            return composite;
        }
    }


    可以看到,这个Service1类实现了在契约中声明的IService1接口(服务契约),也使用到了CompositeType类(数据契约);实现了GetData以及GetDataUsingDataContract这两个服务契约中功能,这些功能即为WCF服务允许外部程序进行调用的功能。
     
    四、寄宿(Host)WCF服务
    有2种常见的寄宿方式:
            1)一种是为一组WCF服务创建一个托管的应用程序,通过手工启动程序的方式对服务进行寄宿,所有的托管的应用程序均可作为WCF服务的宿主,比如 Console应用、Windows Forms应用和ASP.NET应用等,我们把这种方式的服务寄宿方式称为自我寄宿(Self Hosting)。
            2)另一种则是通过操作系统现有的进程激活方式为WCF服务提过宿主,Windows下的进程激活手段包括IIS、Windows Service或者WAS(Windows Process Activation Service)等
     
    无论采用哪种寄宿方式,在为某个服务创建 ServiceHost的过程中,WCF框架内部会执行一系列的操作,其中最重要的步骤就是为服务创建服务描述(Service Description)
     
    本例以第一种为例,建立一个WinForm应用作为托管程序,在VS2010中,建立一个普通的WinForm程序(以frameword4.0为例),如下图:
     
    在工程中,添加对System.ServiceModel的引用,并添加对刚才生成的WcfService1.dll的引用,然后在Form上添加一个Button和一个Label控件,如下图:

     
    在WinForm工程中添加对要托管的WCF服务的描述,既可以通过代码实现,也可以通过工具生成。本例在VS2010下,通过Tools-WCF Service Configeration Editor工具生成。
    点开后,通过菜单的File-New Config新建一个描述文件,然后点击Service页面的Create a New Service,弹出如下界面:

    点击Browse...按钮,选中刚才生成的WcfService1.dll,并选中其中的Service1服务,点击下一步,弹出如下界面:

    这个界面中要选择使用的契约,默认即可,点击下一步,弹出如下界面:

    这个界面中要选择使用的网络通讯协议,选择最通用的HTTP协议,并在下一个界面中选择基本的Http服务(Basic WebService interoperablitity),
    在接下来的界面中,输入访问地址,其它程序可以通过这个地址来访问本WCF服务。

    完成这一步之后,接下来还有一些设置,我也不清楚用途,略去,最后点击File-Save,生成一个App.config文件。这里把该文件贴上来:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="NewBehavior0">
                        <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8585/wcf1/metadata" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="NewBehavior0" name="WcfService1.Service1">
                    <endpoint address="" binding="basicHttpBinding"
                        bindingConfiguration="" name="ep1" contract="WcfService1.IService1" />
                    <host>
                        <baseAddresses>
                            <add baseAddress="http://localhost:8585/wcf1" />
                        </baseAddresses>
                    </host>
                </service>
            </services>
        </system.serviceModel>
    </configuration>


     
    把该App.config文件放在与WinForm工程的根目录下(与Form1.cs同一目录),还需要在VS中将该文件加入到工程中。
     
     
    添加Button控件的处理函数:
    private void button1_Click(objectsender, EventArgs e)
    {
        System.ServiceModel.ServiceHosthost =new System.ServiceModel.ServiceHost(typeof(WcfService1.Service1));
        host.Open();
        this.label1.Text= "opened";
    }

     
    编译运行,点击界面中的Button控件,即可以将该WCF服务寄宿到该Frm中(关闭窗体后WCF服务结束)。
    注:如果运行时报这个错误(HTTP could not register URL http://+:8585/wcf1/. Your process does not have access rights to this namespace),有可能是权限不足导致,需要使用管理员权限运行。
     
    五、在客户端访问并调用WCF服务
    新建一个WinFrm工程(不要关闭刚才的寄宿界面),在VS菜单中点击Project-Add Service Reference..项,输入刚才在寄宿界面中定义的地址,就可以添加对该WCF服务的引用,如下图:

    在程序中使用如下代码,即可以调用WCF服务中的GetData方法:
     
    ServiceReference1.Service1Clientaa=newServiceReference1.Service1Client();
    MessageBox.Show(aa.GetData(2));
     
     
     
     

    展开全文
  • WCF开发框架形成之旅---WCF的几...WCF寄宿方式是一种非常灵活的操作,可以IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。本文分别对

    转自(http://www.cnblogs.com/wuhuacong/archive/2013/02/22/2922195.html


    WCF开发框架形成之旅---WCF的几种寄宿方式

    WCF寄宿方式是一种非常灵活的操作,可以在IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解。

    1、 WCF服务的IIS服务寄宿

    我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿。这种寄宿方式是最为方便的方式,而且由于服务只需要IIS运行就能自动运行起来,因此广为使用。

    创建这种方式IIS寄宿方式的,只需要在解决方案里面,添加WCF服务应用程序,就可以生成这种的服务模块了。

    这个是一个基于Web的应用程序,创建项目后会生成一个Service1.svc的服务页面,以及相关的WCF服务接口和实现,如下图所示。

    这个就是简单的WCF服务,当然如果是复杂的实际应用,会考虑和数据库打交道,而且可能项目会分成几个进行管理,从而实现更好的逻辑分离操作。

     

    2、 创建WCF服务库为多种寄宿做准备

    除了上面常用的IIS服务寄宿,一般还会有各种各样的寄宿方式,不过如果采用其他方式的寄宿方式,一般会把WCF服务和寄宿方式进行项目的分离,实现更好的重用操作,特别WCF需要考虑多种寄宿方式的情况下。下面是WCF服务库和WCF服务应用程序的介绍说明,先了解一下基础。

    WCF服务库,可以认为是一个包含WCF服务以及契约定义的类库。这里WCF服务库还不能直接运行,你可以在其他项目里引用,在宿主里启用托管这个库。

    而WCF应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定义,可以直接看到运行的效果。此项目模板应该是基于IIS托管的程序。

    前者一般考虑WCF服务设计的时候,服务类的定义为单独的库,可以为其它项目使用。提高代码的复用性。后者在开发基于IIS托管的WCF服务程序时,比较多见,自学的时候也可以使用这种类型。当然你也可以修改这些代码,比如把WCF服务程序里的类,移到一个单独的类库里。

    创建WCF服务库,可以理解为我们开发.NET程序时创建的一个类库模块,不含界面,如下所示,创建一个WCF服务库。

    确定后就只有一个示例服务Service1生成了。

    这里,我们为了演示,就不修改任何它们的代码,原始的代码如下所示。

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace WcfServiceLibrary
    {
        public class Service1 : IService1
        {
            public string GetData(int value)
            {
                return string.Format("You entered: {0}", value);
            }
    
            public CompositeType GetDataUsingDataContract(CompositeType composite)
            {
                if (composite == null)
                {
                    throw new ArgumentNullException("composite");
                }
                if (composite.BoolValue)
                {
                    composite.StringValue += "Suffix";
                }
                return composite;
            }
        }
    }
    复制代码

    3、 WCF服务的控制台程序寄宿

    这种也是一种常见的WCF服务寄宿方式,通过启动一个类似DOS窗口的控制台软件,实现WCF服务的动态寄宿,关闭控制台程序,服务就自然终止。

    这种方式很简单,创建一个控制台程序,然后添加WCF服务类库的项目应用,在Main函数里面添加下面代码即可实现。

    复制代码
    namespace WcfService_HostConsole
    {
        class Program
        {
            static void Main(string[] args)
            {            
                try
                {
                    ServiceHost serviceHost = new ServiceHost(typeof(Service1));
                    if (serviceHost.State != CommunicationState.Opened)
                    {
                        serviceHost.Open();
                    }
    
                    Console.WriteLine("WCF 服务正在运行......");
                    Console.WriteLine("输入回车键 <ENTER> 退出WCF服务");
                    Console.ReadLine();
                    serviceHost.Close();
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }
    }
    复制代码

     

    4、 WCF服务的Winform程序寄宿

    和控制台程序一样,我们创建一个Winform项目,然后在窗体启动代码里面添加寄宿方式的代码即可,为了较好的响应体验,可以使用后台线程程序进行服务启动,如下所示。

    复制代码
    namespace WcfService_HostWinform
    {
        public partial class FrmMain : Form
        {
            ServiceHost serviceHost = null;
            BackgroundWorker worker = null;
    
            public FrmMain()
            {
                InitializeComponent();
    
                worker = new BackgroundWorker();
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    
                if (!worker.IsBusy)
                {
                    tssTips.Text = "正在启动......";
                    lblTips.Text = tssTips.Text;
                    worker.RunWorkerAsync();
                }
            }
    
            void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                try
                {
                    serviceHost = new ServiceHost(typeof(Service1));
                    if (serviceHost.State != CommunicationState.Opened)
                    {
                        serviceHost.Open();
                    }
    
                    e.Result = "正常";
                }
                catch (Exception ex)
                {
                    e.Result = ex.Message;
                }
            }
    
            void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Result != null)
                {
                    if (e.Result.ToString() == "正常")
                    {
                        tssTips.Text = "服务正在进行侦听......";
                    }
                    else
                    {
                        tssTips.Text = string.Format("错误:{0}", e.Result);
                    }
    
                    lblTips.Text = tssTips.Text;
                }
            }
            ...........................
        }
    }
    复制代码

    当然为了防止Winform程序被不小心关闭,可以添加托盘代码,把程序缩小到托盘图标里面。

     

    5、 WCF服务的Windows 服务程序寄宿

    这种方式的服务寄宿,和IIS一样有一个一样的优点,系统启动后,WCF服务也会跟着启动了,不用人工干预,也是一种较好的寄宿方式。

    为了实现这种方式的寄宿,我们创建一个控制台程序,然后添加响应的Window服务和安装程序类

    然后在服务类启动里面添加WCF的寄宿代码,如下所示。

    复制代码
        public class ServiceManager : ServiceBase 
        {
            private static object syncRoot = new Object();//同步锁
            private ServiceHost serviceHost = null; //寄宿服务对象
    
            public ServiceManager()
            {
                this.ServiceName = Constants.ServiceName;
            }
    
            /// <summary>
            /// 设置具体的操作,以便服务可以执行它的工作。
            /// </summary>
            protected override void OnStart(string[] args)
            {
                try
                {
                    serviceHost = new ServiceHost(typeof(Service1));
                    if (serviceHost.State != CommunicationState.Opened)
                    {
                        serviceHost.Open();
                    }
                }
                catch (Exception ex)
                {
                    LogTextHelper.Error(ex);
                }
    
                LogTextHelper.Info(Constants.ServiceName + DateTime.Now.ToShortTimeString() + "已成功调用了服务一次。");
    
                LogTextHelper.Info(Constants.ServiceName + "已成功启动。");
            }
    复制代码

    为了实现通过该控制台程序实现参数化安装和卸载服务,我们需要拦截控制台的参数,并进行相应的操作,如下所示。

    复制代码
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main(string[] args)
            {
                ServiceController service = new ServiceController(Constants.ServiceName);
    
                // 运行服务
                if (args.Length == 0)
                {
                    ServiceBase[] ServicesToRun;
                    ServicesToRun = new ServiceBase[] { new ServiceManager() };
                    ServiceBase.Run(ServicesToRun);
                }
                else if (args[0].ToLower() == "/i" || args[0].ToLower() == "-i")
                {
                    #region 安装服务
                    if (!ServiceIsExisted(Constants.ServiceName))
                    {
                        try
                        {
                            string[] cmdline = { };
                            string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
    
                            TransactedInstaller transactedInstaller = new TransactedInstaller();
                            AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
                            transactedInstaller.Installers.Add(assemblyInstaller);
                            transactedInstaller.Install(new System.Collections.Hashtable());
    
                            TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10);
                            service.Start();
                            service.WaitForStatus(ServiceControllerStatus.Running, timeout);
                        }
                        catch (Exception ex)
                        {
                            LogTextHelper.Info(ex);
                            throw;
                        }
                    }
                    #endregion
                }
                else if (args[0].ToLower() == "/u" || args[0].ToLower() == "-u")
                {
                    #region 删除服务
                    try
                    {
                        if (ServiceIsExisted(Constants.ServiceName))
                        {
                            string[] cmdline = { };
                            string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
    
                            TransactedInstaller transactedInstaller = new TransactedInstaller();
                            AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
                            transactedInstaller.Installers.Add(assemblyInstaller);
                            transactedInstaller.Uninstall(null);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogTextHelper.Info(ex);
                        throw;
                    } 
                    #endregion
                }
            }
    复制代码

    编译程序成功后,我们添加两个批处理的DOS脚本来实现执行程序的自动安装和卸载,如下所示。

    安装脚本

    "WcfService_HostWinService.exe" -i
    pause

    卸载脚本

    "WcfService_HostWinService.exe" -u
    pause

    顺利执行脚本后,服务列表里面就增加一个服务项目了。

    卸载操作,直接执行脚本就会卸载服务,非常方便哦。

     

    6、 WCF服务的Web寄宿

    当然,除了以上几种方式,这种以WCF服务库的方式,也可以在Web方式进行寄宿(IIS方式),这种方式更简单,添加一个后缀名的svc的文件,只需要一行代码即可,如下所示。

     

    7、 使WCF服务支持GET方式调用

    有时候,我们为了需要,可能通过一个小程序发布一个服务,然后供其他程序进行调用,可能是Web,也可以是Winform,但是我们是想提供一个基于HTTP,GET或者POST方式来实现接口的调用的,例如,提供一个JSON格式或者文本格式的内容返回操作。

    如果是整合在Winform里面,那么我们在Winform里面添加一个WCF的项,修改里面的代码就可以了,如下所示。

    首先要在使用GET方式的WCF服务接口的添加说明。如果是POS方式,增加设置有点不同([WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)])。

    复制代码
    namespace WcfServiceForWinform
    {
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            void DoWork();
    
            [OperationContract]
            [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
            string GetData(int value);
        }
    }
    复制代码

    第二,在实现类里面添加相应的设置

    复制代码
    namespace WcfServiceForWinform
    {
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Service1 : IService1
        {
            public void DoWork()
            {
            }
    
            public string GetData(int value)
            {
                return string.Format("You entered: {0}", value);
            }
        }
    }
    复制代码

    配置文件如下所示,颜色标注特别的要注意:

    复制代码
    <?xml version="1.0"?>
    <configuration>
    
      <system.web>
        <compilation debug="true"/>
      </system.web>
    
      <system.serviceModel>
        <services>
          <service name="WcfServiceForWinform.Service1"  behaviorConfiguration="ServiceConfig">
            <endpoint address="" binding="webHttpBinding"
                      bindingConfiguration="webHttpBindingWithJsonP" behaviorConfiguration="webHttpBehavior"
                      contract="WcfServiceForWinform.IService1">
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:9000/Service1/" />
              </baseAddresses>
            </host>
          </service>
        </services>
    
        <bindings>
          <webHttpBinding>
            <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true"  />
          </webHttpBinding>
        </bindings>
        
        <behaviors>
          <endpointBehaviors>
            <behavior name="webHttpBehavior">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
          
          <serviceBehaviors>
            <behavior name="ServiceConfig">
              <serviceMetadata httpGetEnabled="True" policyVersion="Policy15"/>
              <serviceDebug includeExceptionDetailInFaults="False"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      </system.serviceModel>
    
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
      </startup>
    </configuration>
    复制代码

    运行Winform程序,启动了WCF服务后,我们可以在浏览器(Chrome)上进行操作,如下结果所示。

    从上图我们可以看到,这个通过Winform启动起来的WCF服务,连接也能通过GET方式进行接口调用了,接口可以通过参数进行传递,对于一些方便传输数据的接口如JSON接口,就是一种非常方便的调用了。

    展开全文
  • 一般的文章中都写到了WCF可以采用多种宿主方式,但是对于控制台宿主和Winform宿主有哪些区别,多数没有写清楚。 对于服务端来说,WCF消息监听和接收体系通过IO线程池并发的处理来自客户端的服务调用请求,所以并发...

    一般的文章中都写到了WCF可以采用多种宿主方式,但是对于控制台宿主和Winform宿主有哪些区别,多数没有写清楚。

    对于服务端来说,WCF消息监听和接收体系通过IO线程池并发的处理来自客户端的服务调用请求,所以并发抵达的服务调用请求消息能够得到及时的处理。但是,服务操作具体在那个线程线程执行,则是通过WCF的并发处理体系决定的。

    在默认的情况下,WCF采用这样的机制控制并发操作的执行:如果在进行服务寄宿(IIS寄宿方式除外)的过程中,当前线程存在同步上下文,会将其保存在服务端分发运行时。等到需要执行服务操作的时候,WCF并发体系会判断分发运行时的同步上下文是否存在,如果不存在则在各个的线程中执行服务操作,否则,服务操作会被封送到该同步上下文中执行。

    如果我们将某个服务寄宿于一个控制台(Console)应用之中,由于控制台程序的当前同步上下文为空,按照上面的并发操作执行机制,所有的请求操作会在各自的线程中并行地执行。所以,在流量允许的范围内,并发的请求能够得到及时地处理。

    如果我们通过Windows Forms应用作为某个服务的宿主,服务操作的执行永远是以同步的方式执行的。也就是说,在某个时刻,仅仅只有针对某个服务调用的服务操作被执行,其他的调用请求都将被放入一个等待队列中。如果等待的时候超出了设定的超时时限(这在高并发的情况下会比较频繁),客户端会抛出TimeoutException异常。我们将服务操作与服务寄宿程序线程自动绑定的现象称为服务的线程亲和性(Thread Affinity)

    在这种情况下,由于服务操作执行在UI线程中,可以正常得对Windows窗体上的控件进行操作。如果,你希望服务操作能够并发地被执行,就不得不打破这种线程亲和性,我们可以按照监控程序中的方式在服务类型上应用ServiceBehaviorAttribute特性将UseSynchronizationContext属性设置成False。但是在这种情况下,如果你需要对控件进行操作,你就需要调用Control类型的Invoke或者BeginInvoke方法,或者按照我们监控程序的方式借助于SynchronizationContext对象了。UseSynchronizationContext在ServiceBehaviorAttribute的定义如下面的代码所示,该属性的默认值为True。

       1: [AttributeUsage(AttributeTargets.Class)]
       2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
       3: {
       4:     //其他成员    
       5:     public bool UseSynchronizationContext { get; set; }
       6: }


    展开全文
  • WCF的相关概念信息就不此赘述了,网上一搜一大把。 现在让我们动手搭建我们的第一个wcf程序吧,具体流程如下: 1. 新建立空白解决方案,并解决方案中新建项目,项目类型为:WCF服务应用程序。 2、建立完成后...
  • WCF--建立简单的WCF服务

    千次阅读 热门讨论 2014-10-31 20:47:01
    建立简单的WCF服务
  • 使用WCF的时候,客户端运行报错:
  • WCF服务自我寄宿

    千次阅读 2016-07-05 16:38:46
    WCF寄宿方式是一种非常灵活的操作,可以寄宿各种进程之中,常见的寄宿有: IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。 签名 前面...
  • WCF Data Services vs WCF RIA Services
  • 一个傻瓜式的Windows服务宿主模式下的WCF的完整示例 只注重于实现,不讲理论
  • WCF服务自托管(Self-Hosting)

    千次阅读 2016-08-17 11:51:59
    WCF寄宿方式是一种非常灵活的操作,可以寄宿各种进程之中,常见的寄宿有:IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。   当客户端和...
  • WCF服务宿主及其跨域问题

    万次阅读 2013-12-18 11:08:50
    WCF服务不是一个能单独执行的程序,需要寄宿在相关的可执行程序上执行,常见的宿主方式有IIS, 控制台(Winform,wpf), Windows Service这几种方式,使用Silverlight调用发布Wcf服务会发生跨域错误如图: 什么是跨域...
  • WCF的几种寄宿方式

    2013-08-09 08:55:35
    http://www.cnblogs.com/wuhuacong/archive/2013/02/22/2922195.html
  • WCF实战第一示例

    千次阅读 2015-08-28 21:44:03
     Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分。由 .NET Framework 3.0 开始引入。  WCF的最终目标是通过进程或不同...
  • WCF作为服务端,目前是寄宿在IIS,客户端是普通的winform,就想简单的做一个“发送请求”、“返回结果”的功能。 但是服务端显示参数一直是null。 用的json格式。 WCF接口代码: [OperationContract] ...
  • WCF服务寄宿Winform中,运行外网的服务器上,在内网的浏览器上可以访问到数据,如下: ![图片说明](https://img-ask.csdn.net/upload/201906/17/1560757639_468759.png) 但是添加服务引用时,报错,如图:...
  • WCF寄宿方式是一种非常灵活的操作,可以IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。本文分别对这几种方式进行详细介绍并开发例子进行...
  • WCF实现HTPP URL带参数形式(http://xxxx.com?x=y&a=b)访问
  • WCF 之 计算器实例

    千次阅读 热门讨论 2015-04-28 16:49:38
    对于WCF,我们有了前面的理论基础,今天通过一个计算器的实例主要给大家讲解怎么一步一步地创建一个完整的WCF应用。 一、创建整个解决方案    Calculator.Service:一个类库项目,定义服务契约(Service ...
1 2 3 4 5 ... 17
收藏数 329
精华内容 131
关键字:

wcf 创建 寄宿在winform