Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF向所有客户端广播消息_C#_Wcf_Message_Broadcast - Fatal编程技术网

C# WCF向所有客户端广播消息

C# WCF向所有客户端广播消息,c#,wcf,message,broadcast,C#,Wcf,Message,Broadcast,我有一个WCF服务和客户端应用程序——在本例中,我使用命名管道。服务和客户端能够相互通信。我要做的就是使用回调方法向所有客户端广播消息 在服务中,客户端使用两种方法在服务中注册自己: public void RegisterInService(Guid clientID) { ICallbacks callback = OperationContext.Current.GetCallbackChannel<ICallbacks>();

我有一个WCF服务和客户端应用程序——在本例中,我使用命名管道。服务和客户端能够相互通信。我要做的就是使用回调方法向所有客户端广播消息

在服务中,客户端使用两种方法在服务中注册自己:

public void RegisterInService(Guid clientID)
{
            ICallbacks callback = OperationContext.Current.GetCallbackChannel<ICallbacks>();

            lock (clients)
            {
                if (!clients.ContainsKey(clientID))
                {
                    clients.Add(clientID, callback);
                }
            }
}
用于存储特定客户端信息的字典:

private static Dictionary<Guid, ICallbacks> clients = new Dictionary<Guid, ICallbacks>();
WCF服务行为已按以下方式配置:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
现在,在服务中,我有另一种方法,比如说更高级的操作。在这个方法中,我想执行另一个方法来向所有注册的客户机广播消息

代码如下:

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();

}
现在,假设内存中有三个客户机实例(一个应用程序执行三次)。一旦我从一个客户机调用方法
MainProcessActions()
,回调方法将只针对这个特定的客户机执行。其他客户端似乎忽略了回调方法
UpdateClientData(字符串数据)

你们能给我一些建议我怎样才能解决这个问题

简而言之,我希望将数据从服务发送到所有注册的客户端

#编辑

我有一些更新。
UpdateClientData(字符串数据)
方法实际上由所有客户端执行。。。问题在于使用从服务接收的数据在Windows窗体中设置TextBox控件

以下是此方法的主体:

public void UpdateClientData(string data)
{
     this.DataFromService = data;
}
在代码的后面部分,我将使用属性
DataFromService
在MainForm类的TextBox控件中设置文本

看起来TextBox控件的文本只能由客户端的一个实例设置

有趣的是,当我将对TextBox控件的引用传递给实现
UpdateClientData
方法的类时,我就能够在所有客户机中同时设置TextBox控件中的文本

有什么建议吗

#编辑

下面是我使用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;
    }

}
另一件有趣的事。当我将整个服务通信配置(创建通道、回调方法的实现)移动到MainForm类中时,一切都正常工作——我能够为客户机的所有实例设置TextBox


问候

您会说“稍后在代码中,我将使用属性DataFromService在MainForm类的TextBox控件中设置文本。”。你能给我看看这个密码吗?你好,伊戈尔。看看这篇文章——它已经更新了,现在包含了你提到的代码。很抱歉离开了——这是假期。如果问题仍然相关,我建议修改
CallbackBehavior
属性并在那里添加
ConcurencyMode=Multiple
(或至少
可重入
)。默认情况下,它是single,这意味着当一个线程(uione)正在执行
ExecuteOnServiceSide
方法时,回调不会启动。
public void UpdateClientData(string data)
{
     this.DataFromService = data;
}
[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;
    }

}
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;
    }
}