我有一个WCF服务和客户端应用程序 - 我在这种情况下使用命名管道。服务和客户能够相互通信。我想做的就是使用回调方法向所有客户端广播消息。
在服务中,我有两种方法可以让客户在服务中注册自己:
存储有关特定客户的信息的字典:
private static Dictionary<Guid, ICallbacks> clients = new Dictionary<Guid, ICallbacks>();
在服务中注册客户端的方法:
public void RegisterInService(Guid clientID)
{
ICallbacks callback = OperationContext.Current.GetCallbackChannel<ICallbacks>();
lock (clients)
{
if (!clients.ContainsKey(clientID))
{
clients.Add(clientID, callback);
}
}
}
取消注册客户端的方法:
public void UnregisterFromService(Guid clientID)
{
lock(clients)
{
if (clients.ContainsKey(clientID))
clients.Remove(clientID);
}
}
WCF服务行为已按以下方式配置:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
现在,在服务中我有另一种方法,让我们说更多&#34; advanced&#34;操作。在这个方法中,我想执行另一种方法来向所有注册的客户端广播消息。
以下是代码:
public void MainProcessActions()
{
SendMessageToAllClients("Send to all clients ...");
}
private void SendMessageToAllClients(string data)
{
StreamWriter file = new System.IO.StreamWriter(@"E:\Temp\ClientsInvokingEvidence.txt", true);
lock (clients)
{
foreach (KeyValuePair<Guid, ICallbacks> client in clients)
{
client.Value.UpdateClientData(data);
file.WriteLine("Invoking method for client ID : {0}", client.Key);
}
}
file.Close();
}
这是接口中的回调方法声明:
public interface ICallbacks
{
[OperationContract(IsOneWay = true)]
void UpdateClientData(string data);
}
现在,让我们说我在内存中有三个客户端实例(一个应用程序执行三次)。一旦我从其中一个客户端调用方法MainProcessActions()
,就只为该特定客户端执行回调方法。似乎其他客户端忽略了回调方法UpdateClientData(string data)
。
你能给我一些提示,我该如何解决这个问题?
简而言之,我想将服务中的数据发送给所有注册客户。
#edit
我有一些更新。 UpdateClientData(string data)
方法实际上是由所有客户端执行的...问题在于使用从服务接收的数据来设置Windows窗体中的TextBox控件。
以下是此方法的主体:
public void UpdateClientData(string data)
{
this.DataFromService = data;
}
稍后在代码I中使用属性DataFromService
在MainForm类的TextBox控件中设置文本。
看起来TextBox控件的文本只能由一个客户端实例...
设置有趣的是,当我将对TextBox控件的引用传递给实现UpdateClientData
方法的类时,我可以同时在所有客户端的TextBox控件中设置文本。
有什么建议吗?
#edit
以下是我使用DataFromService属性的代码部分。
此属性是以下类的成员:
[CallbackBehavior(UseSynchronizationContext = false)]
class WCFServiceCommunication : ICallbacks
{
public string DataFromService;
...
public WCFServiceCommunication()
{
binding = new NetNamedPipeBinding();
pipeFactory = new DuplexChannelFactory<IGeneralContract>(this, binding, new EndpointAddress("net.pipe://localhost/SomeName"));
pipeProxy = pipeFactory.CreateChannel();
ClientID = Guid.NewGuid();
}
public void ExecuteOnServiceSide()
{
pipeProxy.MainProcessActions();
}
public void RegisterClient()
{
pipeProxy.RegisterInService(ClientID);
}
public void UnregisterClient()
{
pipeProxy.UnregisterFromService(ClientID);
}
public void UpdateClientData(string data)
{
// here I'm able to verify that this method actually has been invoked by service for each instance of the client
DataFromService = data;
}
}
在UI代码(Windows窗体)中:
class MainForm : Form
{
private WCFServiceCommunication wcfCommunication;
....
public MainForm()
{
InitalizeComponent();
wcfCommunication = new WCFServiceCommunication();
wcfCommunication.RegisterClient();
}
...
private void btnCheckForUpdates_Click(object sender, EventArgs e)
{
// here, on service side method MainProcessActions() is called
// in this method I'm calling broadcast method
wcfCommunication.ExecuteOnServiceSide();
textBox1.Text = wcfCommunication.DataFromService;
}
}
另一个有趣的事情。当我将整个服务通信配置(创建通道,回调方法的实现)移动到MainForm类中时,一切正常 - 我能够为客户端的所有实例设置TextBox。
问候!