如何在WCF服务和主机应用程序之间进行通信?

我通过本教程创建了一个WCF服务。 这很好用,没问题。 现在我在托管应用程序中托管服务。 但与此同时,我希望将客户端的输入用于主机应用程序中的服务。

我不需要客户端和服务之间的双工通信。 我只需要服务和主机通信之间的通信。

处理这个问题的最佳方法是什么?

我设法使用这个问题的信息来解决它。 其中指出服务类也可以传递给主机。 然后就像添加一个响应来自Service的事件的事件监听器一样简单。

这就像线程之间的通信。 您需要一些具有正确锁定/同步的共享变量。 您的主机应用程序将写入此变量,您的服务将能够从该变量读取。

有一个框架和教程似乎可以很好地处理Codeplex上的WPF服务主机这个问题。

编辑:更新以说明由WPF服务主机模板创建的技术。

WPF服务主机是Visual Studio的模板,用于创建框架应用程序和测试客户端。 我将在这里描述相关的部分。

这是骨架项目的样子:

骨架项目

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中

                       

和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(); } } }