【发布时间】:2011-06-17 14:29:19
【问题描述】:
我试图弄清楚为什么当您有多个回调客户端使用众所周知的发布-订阅模式连接时,当一个故障或一个断开连接而不取消订阅时,所有客户端状态都设置为已关闭然后故障。
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallback))]
public interface IPubSubService
{
[OperationContract(IsOneWay = false, IsInitiating = true)]
void Subscribe();
[OperationContract(IsOneWay = false, IsInitiating = true)]
void UnSubscribe();
[OperationContract(IsOneWay = false)]
void BroadcastMessage(string message);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class PubSubService : IPubSubService
{
private ICallback _callbackClient;
public static event Action<string> _action;
public void Subscribe()
{
_callbackClient = OperationContext.Current.GetCallbackChannel<ICallback>();
_action += ActionInvoked;
}
public void UnSubscribe()
{
_action -= ActionInvoked;
}
public void BroadcastMessage(string message)
{
_action.Invoke(message);
}
public void ActionInvoked(string message)
{
_callbackClient.SendMessage(message);
}
}
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void SendMessage(string message);
}
// The Publisher that doesn't subscribe only sends the message
[CallbackBehaviorAttribute(UseSynchronizationContext = false)]
public partial class Form1 : Form, ICallback
{
public Form1()
{
InitializeComponent();
}
private ServiceClient _proxy;
private void button1_Click(object sender, EventArgs e)
{
try
{
_proxy = new ServiceClient(new InstanceContext(this));
_proxy.BroadcastMessage(textBox1.Text);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
public void SendMessage(string message)
{
}
}
public static class ControlExtensions
{
public static void Invoke(this Control Control, Action Action)
{
Control.Invoke(Action);
}
}
public class ServiceClient : DuplexClientBase<IPubSubService>, IPubSubService
{
public ServiceClient(InstanceContext callbackInstance)
: base(callbackInstance)
{ }
public void Subscribe()
{
Channel.Subscribe();
}
public void UnSubscribe()
{
Channel.UnSubscribe();
}
public void BroadcastMessage(string message)
{
Channel.BroadcastMessage(message);
}
}
// The Subscriber
[CallbackBehaviorAttribute(UseSynchronizationContext = false)]
public partial class Form1 : Form, ICallback
{
public Form1()
{
InitializeComponent();
}
private ServiceClient _proxy;
private void button1_Click(object sender, EventArgs e)
{
_proxy = new ServiceClient(new InstanceContext(this));
_proxy.Subscribe();
this.Invoke(() => textBox1.AppendText("Subscribed..."));
}
public void SendMessage(string message)
{
this.Invoke(() => textBox1.AppendText(message + "\r\n"));
}
private void button2_Click(object sender, EventArgs e)
{
if (_proxy != null && _proxy.State == CommunicationState.Opened)
{
_proxy.UnSubscribe();
}
}
private void button3_Click(object sender, EventArgs e)
{
Thread.Sleep(new TimeSpan(0, 1, 0));
}
}
public static class ControlExtensions
{
public static void Invoke(this Control Control, Action Action)
{
Control.Invoke(Action);
}
}
public class ServiceClient : DuplexClientBase<IPubSubService>, IPubSubService
{
public ServiceClient(InstanceContext callbackInstance) : base(callbackInstance)
{ }
public void Subscribe()
{
Channel.Subscribe();
}
public void UnSubscribe()
{
Channel.UnSubscribe();
}
public void BroadcastMessage(string message)
{
Channel.BroadcastMessage(message);
}
}
// config for both clients publisher and subscriber
<configuration>
<system.windows.forms jitDebugging="true" />
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTCPBinding">
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true"/>
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint
address="net.tcp://localhost:8008/PubSubService"
binding="netTcpBinding"
bindingConfiguration="netTCPBinding"
contract="ServiceLibrary.IPubSubService"
name="netTCPBinding">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
<startup>
</startup>
</configuration>
// config for Service
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="ServiceLibrary.PubSubService">
<endpoint address="net.tcp://localhost:8008/PubSubService"
binding="netTcpBinding"
bindingConfiguration="netTCPBinding"
contract="ServiceLibrary.IPubSubService"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="netTCPBinding" closeTimeout="00:00:10" openTimeout="00:00:10" receiveTimeout="00:00:10" sendTimeout="00:00:10" transactionFlow="false" transferMode="Buffered" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="1000" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true"/>
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
【问题讨论】: