如何通过wcf服务更新宿主项目中的winform控件?

How to update winform controls in host project through wcf service?

我有一个客户端解决方案,它是 windows 表单项目,带有一个表单和按钮 "Connect"(到 wcf 服务)。

我还有另一个解决方案,它由 wcf 库项目(用于 wcf 服务)和 windows 表单项目(用于主机)组成。 WCF 服务实现最简单的方法 Connect 增加计数器并调用通知客户端的回调。如何通过 wcf 服务(Connect 方法)更新宿主项目中的表单控件?

IMonitoringService:

[ServiceContract(CallbackContract = typeof(IMonitoringServiceCallback))]
public interface IMonitoringService
{
    [OperationContract(IsOneWay = true)]
    void Connect(string name);
}

public interface IMonitoringServiceCallback
{
    [OperationContract(IsOneWay = true)]
    void Notify(string msg);
}

监控服务:

public class MonitoringService : IMonitoringService
{ 
    private int _registeredUsers = 0;

    public void Connect(string name)
    {
        _registeredUsers++;

        // How i should update textBox in Host form here?
        // Something like this: textBox1.Text = name; 

        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
        callback.Notify(_registeredUsers.ToString());
    }
}

主持人:

public partial class MonitoringListenerForm : Form
{
    private ServiceHost host = null;

    public MonitoringListenerForm()
    {
        InitializeComponent();
    }

    private void btnStartListen_Click(object sender, EventArgs e)
    {
        if (host == null)
        {
            host = new ServiceHost(typeof(MonitoringService));
            host.Open();

            textBox1.Text = "Host started @ " + DateTime.Now.ToString();
        }
    }

    private void btnStopListen_Click(object sender, EventArgs e)
    {
        host.Close();
        host = null;
        textBox1.Text = "Host closed @ " + DateTime.Now.ToString();
    }
}

客户:

public partial class MonitoringClientForm : Form, IMonitoringServiceCallback
{
    private InstanceContext instanceContext = null;
    private MonitoringServiceClient client = null;

    public MonitoringClientForm()
    {
        InitializeComponent();
    }

    public void Notify(string msg)
    {
        textBox1.Text = "Callback: " + msg;
    }

    private void btnConnect_Click(object sender, EventArgs e)
    {
        instanceContext = new InstanceContext(this);
        client = new MonitoringServiceClient(instanceContext);

        try
        {
            client.Connect("client1");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }         
}

更新:例如,在监控监听器中,当客户端连接时,文本框应该显示客户端的名称。

enter image description here

根据你的描述,可以使用Callbackcontract。 Callback函数会调用客户端代码,将textbox中需要更新的参数放入回调函数中,传递给客户端执行。客户端将使用从服务器端传递的参数更新文本框。

这是我的演示。使用的绑定是 wsdualhttpbinding。

       public class MonitoringService : IMonitoringService
{
    private  static int _registeredUsers = 0;

    public void Connect(string name)
    {
        _registeredUsers++;
        Console.WriteLine("success");
        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
         callback.Notify(_registeredUsers.ToString());
    }
}

这是服务器的代码。服务器端通过回调调用客户端代码,传递一个参数。客户端会拿到参数并执行。

     private void button1_Click(object sender, EventArgs e)
    {
        instanceContext = new InstanceContext(this);
        var client = new MonitoringServiceClient(instanceContext);

        try
        {
            client.Connect("client1");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form1());
    }

    public void Notify(string msg)
    {
        textBox1.Text = "Callback: "+msg;
    }

这是客户端代码。客户端实现回调。

这是结果。

       public class MonitoringService : IMonitoringService
{
    private  static int _registeredUsers = 0;

    public void Connect(string name)
    {
        _registeredUsers++;
        Console.WriteLine("success");
        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
        callback.Notify("name");
    }
}

正在修改 Notify 中的参数。

您可以通过修改 Notify 中的参数来更新客户端文本框的值。

更新

textbox的值可以通过反射获取,然后发送给客户端。

      public void Connect(string name)
    {
        var callback = OperationContext.Current.GetCallbackChannel<IMonitoringServiceCallback>();
        Form1 form = new Form1();
        Type type = typeof(Form1);
        System.Reflection.FieldInfo propertyInfo = type.GetField("textBox1");
        TextBox textBox = (TextBox)propertyInfo.GetValue(form);
        callback.Notify(textBox.Text);
    }