当我使用serviceChild创建一个带有serviceManager的通道时, 调用serviceManager的回调。 它会freez。
所有服务绑定都是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();
}
答案 0 :(得分:4)
我喜欢这样构建我的WCF解决方案:
合同(类库)
包含所有服务,操作,故障和数据协定。可以在纯.NET-to-.NET场景中在服务器和客户端之间共享
服务实施(类库)
包含实现服务的代码,以及实现此目的所需的任何支持/帮助程序方法。没别了。
服务主机(可选 - 可以是Winforms,Console App,NT Service)
包含用于调试/测试的服务主机,或者也可能用于生产。
这基本上给了我服务器方面的东西。
在客户端:
客户端代理(类库)
我喜欢将我的客户端代理打包到一个单独的类库中,以便它们可以被多个实际的客户端应用程序重用。这可以使用svcutil或&#34;添加服务参考&#34;并手动调整生成的可怕app.config,或者使用ClientBase<T>
或ChannelFactory<T>
构造手动实现客户端代理(共享契约程序集时)。
1-n个实际客户(任何类型的应用)
通常只会引用客户端代理程序集,或者也可能是合同程序集,如果它正在共享的话。这可以是ASP.NET,WPF,Winforms,控制台应用程序,其他服务 - 您可以命名。
这是受到Miguel Castro的Extreme WCF screen cast在DotNet Rocks电视上与Carl Franklin的启发 - 强烈推荐的屏幕演员!