私は1つのexeを持っています。このexeで。私はサービスを開始し、それをserviceManagerと呼び、次に別のサービスを開始し、それをserviceChildと呼びます。
serviceChild を使用するときは、serviceManager でチャネルを作成し、serviceManager のコールバックを呼び出します。凍ります。
すべてのサービス バインディングは netnamedpipebinding です。
何が起こったのか誰が教えてくれますか?
そして私のコード:インターフェース:
[ServiceContract]
internal interface IChild
{
[OperationContract]
CommunicationState GetState();
}
[ServiceContract]
public interface IManager
{
[OperationContract]
CommunicationState GetState();
}
と:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.Single)]
public class Child : IChild
{
private readonly Guid _address = Guid.NewGuid();
private readonly ServiceHost _host;
public Guid Address
{
get { return _address; }
}
public Child()
{
_host = new ServiceHost(this);
var binding = new NetNamedPipeBinding();
var clientAddress = Helper.GetClientAddress(_address);
_host.AddServiceEndpoint((typeof(IChild)), binding, clientAddress);
_host.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
_host.AddServiceEndpoint(new UdpDiscoveryEndpoint());
_host.Open();
}
public void Open()
{
if(!Manager.IsRunning()){Manager.Start();}
var binding = new NetNamedPipeBinding();
var endpoint = new EndpointAddress(Constants.ADDRESS_PIPE_SERVER);
using (var factory = new ChannelFactory<IManager>(binding, endpoint))
{
IManager managerChannel = null;
try
{
managerChannel = factory.CreateChannel();
**managerChannel.GetState();**// BUG:<-----
}
catch (Exception ex)
{
MessageBox.Show("ex " + ex);
}
finally
{
Helper.CloseChannel((ICommunicationObject)managerChannel);
}
}
}
public CommunicationState GetState()
{
return _host.State;
}
}
マネージャー:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.Single)]
public class Manager : IManager
{
private static ServiceHost _host;
private static Manager _instance;
private static Manager Instance
{
get { return _instance ?? (_instance = new Manager()); }
}
#region IManager Members
public CommunicationState GetState()
{
return _host.State;
}
#endregion
public static void Start()
{
if (_host != null
&& (_host.State == CommunicationState.Created
|| _host.State == CommunicationState.Opening
|| _host.State == CommunicationState.Opened))
{
return;
}
_host = new ServiceHost(Instance);
var binding = new NetNamedPipeBinding();
var endpoint = Constants.ADDRESS_PIPE_SERVER;
_host.AddServiceEndpoint((typeof (IManager)), binding, endpoint);
_host.Open();
}
public static bool IsRunning()
{
var binding = new NetNamedPipeBinding();
var endpointAddress = new EndpointAddress(Constants.ADDRESS_PIPE_SERVER);
var factory = new ChannelFactory<IManager>(binding, endpointAddress);
IManager managerChannel = null;
try
{
managerChannel = factory.CreateChannel();
// wait for server to respond
if (_host != null && _host.State == CommunicationState.Opened)
{
var contextChannel = managerChannel as IClientChannel;
if (contextChannel != null) contextChannel.OperationTimeout = TimeSpan.FromMilliseconds(1000);
}
try
{
managerChannel.GetState();
}
catch (Exception)
{
return false;
}
return true;
}
catch (EndpointNotFoundException e)
{
return false;
}
finally
{
Helper.CloseChannel((ICommunicationObject) managerChannel);
}
}
その他:
internal static class Helper
{
public static void CloseChannel(ICommunicationObject channel)
{
try
{
if (channel.State == CommunicationState.Opened) channel.Close();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
channel.Abort();
}
}
public static string GetClientAddress(object serviceAddress)
{
return string.Format(Constants.ADDRESS_PIPE_CLIENT_FORMAT, serviceAddress);
}
}
internal static class Constants
{
internal static string ADDRESS_PIPE_SERVER = @"net.pipe://localhost/Server";
internal static string ADDRESS_PIPE_CLIENT_FORMAT = @"net.pipe://localhost/Client_{0}";
}
最後に、テスト:
private void ActionLoaded(object sender, RoutedEventArgs e)
{
Manager.Start();
}
private void ActionConnectedSelf(object sender, RoutedEventArgs e)
{
var client = new Child();
client.Open();
}