How to communicate between WCF service and host application?

后端 未结 3 1510
梦如初夏
梦如初夏 2020-12-17 05:27

I created an WCF service through this tutorial. This works great, no problems here. Now I am hosting the service in an Managed Application. But at the same time I would like

3条回答
  •  暖寄归人
    2020-12-17 05:39

    There is a framework and tutorial available that seems to handle this problem quite nicely WPF Service Host on Codeplex.

    EDIT: Updated to illustrate technique created by the WPF Service Host template.

    The WPF Service Host is a template for Visual Studio that creates a skeleton application and test client. I'll describe the relevant pieces here.

    Here's what the skeleton project looks like:

    Skeleton Project

    ClientServiceHost.cs

    using System;
    using System.ServiceModel;
    
    namespace WPFServiceHost1.Service
    {
        public class ClientServiceHost : IDisposable
        {
            private bool _Initalized;
    
            private ServiceHost _InnerServiceHost;
            private MainWindow _MainWindow;
    
            public ClientServiceHost(MainWindow mainWindow)
            {
                _MainWindow = mainWindow;
                InitializeServiceHost();
            }
    
            private void InitializeServiceHost()
            {
                try
                {
                    ClientService clientService = new ClientService(_MainWindow);
                    _InnerServiceHost = new ServiceHost(clientService);
    
                    _InnerServiceHost.Opened += new EventHandler(_InnerServiceHost_Opened);
                    _InnerServiceHost.Faulted += new EventHandler(_InnerServiceHost_Faulted);
                    _InnerServiceHost.Open();
                }
                catch (Exception ex)
                {
                    throw new Exception("Unable to initialize ClientServiceHost", ex);
                }
            }
    
            void _InnerServiceHost_Opened(object sender, EventArgs e)
            {
                _Initalized = true;
            }
    
            void _InnerServiceHost_Faulted(object sender, EventArgs e)
            {
                this._InnerServiceHost.Abort();
    
                if (_Initalized)
                {
                    _Initalized = false;
                    InitializeServiceHost();
                }
            }
    
            #region IDisposable Members
    
            public void Dispose()
            {
                try
                {
                    _InnerServiceHost.Opened -= _InnerServiceHost_Opened;
                    _InnerServiceHost.Faulted -= _InnerServiceHost_Faulted;
                    _InnerServiceHost.Close();
                }
                catch
                {
                    try { _InnerServiceHost.Abort(); }
                    catch { }
                }
            }
            #endregion
        }
    }
    

    MainWindow.xaml

    
        
            
            
        
    
    

    MainWindow.xaml.cs

    using System.Threading;
    using WPFServiceHost1.Service;
    
    namespace WPFServiceHost1
    {
        /// 
        /// Interaction logic for Window1.xaml
        /// 
        public partial class MainWindow : Window
        {
            public SynchronizationContext _SyncContext = SynchronizationContext.Current;
            private ClientServiceHost _ClientServiceHost;
    
            public MainWindow()
            {
                InitializeComponent();
                _ClientServiceHost = new ClientServiceHost(this);
            }
    
            private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                _ClientServiceHost.Dispose();
            }
        }
    }
    

    IClientService.cs

    using System.ServiceModel;
    
    namespace WPFServiceHost1.Service
    {
        [ServiceContract(Namespace = "urn:WPFServiceHost")]
        public interface IClientService
        {
            [OperationContract]
            void ClientNotification(string message);
        }
    }
    

    ClientService.cs

    using System;
    using System.ServiceModel;
    
    namespace WPFServiceHost1.Service
    {
        [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext = false)]
        public class ClientService : IClientService
        {
            private MainWindow _MainWindow;
    
            public ClientService(MainWindow window)
            {
                _MainWindow = window;
            }
    
            #region IClientService Members
            public void ClientNotification(string message)
            {
                try
                {
                    _MainWindow._SyncContext.Send(state =>
                    {
                        _MainWindow.listBox1.Items.Add(message);
                    }, null);
                }
                catch (Exception ex)
                {
                    throw new FaultException(ex.Message);
                }
            }
            #endregion
        }
    }
    

    App.config

    
    
        
            
                
                    
                        
                    
                
            
            
                
                    
                    
                        
                            
                        
                    
                
            
        
    
    

    And the TestClient, Program.cs:

    using System;
    using System.ServiceModel;
    using System.Threading;
    
    namespace TestClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                IClientService proxy = null;
    
                try
                {
                    proxy = ChannelFactory.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8010/ClientService"));
                    Console.WriteLine("Press  when ClientService is running.");
                    Console.ReadLine();
                    Console.WriteLine();
    
                    Console.WriteLine("Sending a single message to ClientService");
                    proxy.ClientNotification("Hello from TestClient");
    
                    Console.WriteLine();
    
                    Console.Write("Enter a valid number to load test ClientService: ");
                    string result = Console.ReadLine();
                    int testCount = Convert.ToInt32(result);
                    int counter = 0;
                    object counterLock = new object();
    
                    while (true)
                    {
                        lock (counterLock)
                        {
                            Thread t = new Thread(() => proxy.ClientNotification(string.Format("Load test from TestClient: {0}", ++counter)));
                            t.Start();
                        }
    
                        if (counter == testCount)
                            break;
                    }
    
                    Console.ReadLine();
                }
                finally
                {
                    ICommunicationObject co = proxy as ICommunicationObject;
                    try
                    {
                        co.Close();
                    }
                    catch { co.Abort(); }
                }
    
                Console.ReadLine();
            }
        }
    }
    

提交回复
热议问题