2011-01-13 13 views
4

私はこのtutorialでWCFサービスを作成しました。これは素晴らしい、問題はここで動作します。 管理対象アプリケーションでサービスをホストしています。しかし同時に、クライアントからの入力をホストアプリケーションのサービスに使用したいと考えています。WCFサービスとホストアプリケーション間の通信方法

クライアントとサービスの間でデュプレックス通信は必要ありません。私はサービスとホストの間のコミュニケーションが必要です。

これに対処するにはどうすればよいでしょうか?

答えて

3

私はこのquestionの情報を使って解決することができました。サービスクラスもホストに渡すことができるという指摘がありました。それから、サービスからのイベントに応答するイベントリスナーを追加するだけで簡単です。

+0

このような場合、あなたのサービスはシングルトンになります。 –

2

スレッド間の通信に似ています。適切なロック/同期を持つ共有変数が必要です。ホストアプリケーションがこの変数に書き込むと、サービスはその変数から読み込むことができます。

+0

ご意見ありがとうございます。さて、私はこの作業を見ることができました。しかし、ホストアプリケーションからサービスオブジェクトの変数部分にアクセスするにはどうすればよいのですか? Host.open()コマンドを使用してサービスをホストしているので、私はそのサービスへの参照を持っていません。 – Martijn

+0

サービスインスタンスの変数にはアクセスしません。あなたの変数は、よく知られたオブジェクトによって共有されなければなりません。例えば、あなたはこのような変数をサービスとホストの両方に公開するimpleton singletonを行うことができます。他のアプローチでは、共有オブジェクトにサービスロケータを使用しています。 –

+0

ホストアプリケーションでシングルトンプロパティを持つ別のオブジェクトを作成する必要があることを意味しますか?サービスからこのオブジェクトへの参照を作成するにはどうすればよいですか?私の最終的な目標は、WCFサービスがクライアントからデータを受け取ったときに、ホストアプリケーションで関数をトリガーすることです。これはシングルトンメソッドを使用して動作しますか? – Martijn

2

この問題を非常にうまく処理していると思われるフレームワークとチュートリアルがあります。WPF Service Host on Codeplex

EDIT:WPFサービスホストテンプレートによって作成された技術を説明するために更新されました。

WPFサービスホストは、スケルトンアプリケーションとテストクライアントを作成するVisual Studioのテンプレートです。ここで関連する部分について説明します。

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

<Window x:Class="WPFServiceHost1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="WPFServiceHost1" Height="344" Width="343" Closing="Window_Closing"> 
    <Grid> 
     <Label Height="28" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="119">Messages received:</Label> 
     <ListBox Margin="21,38,26,21" Name="listBox1" /> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

:ここ

は、スケルトンプロジェクトは次のようになります。

using System.Threading; 
using WPFServiceHost1.Service; 

namespace WPFServiceHost1 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    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を

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.serviceModel> 
     <behaviors> 
      <serviceBehaviors> 
       <behavior name="ClientServiceBehavior"> 
        <serviceDebug includeExceptionDetailInFaults="false" /> 
       </behavior> 
      </serviceBehaviors> 
     </behaviors> 
     <services> 
      <service behaviorConfiguration="ClientServiceBehavior" 
       name="WPFServiceHost1.Service.ClientService"> 
       <endpoint address="ClientService" binding="basicHttpBinding" contract="WPFServiceHost1.Service.IClientService"/> 
       <host> 
        <baseAddresses> 
         <add baseAddress="http://localhost:8010" /> 
        </baseAddresses> 
       </host> 
      </service> 
     </services> 
    </system.serviceModel> 
</configuration> 

そして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<IClientService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8010/ClientService")); 
       Console.WriteLine("Press <Enter> 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(); 
     } 
    } 
} 
関連する問題