【问题标题】:Handling WCF events in another process在另一个进程中处理 WCF 事件
【发布时间】:2012-01-17 02:43:06
【问题描述】:

我有一个不可序列化的对象,我想从一个单独的进程中访问它。我环顾四周,似乎唯一可行的选择是使用 WCF,但我不知道如何做到这一点,因为我是 WCF 的新手。如果我创建一个 WCF 服务,我如何将 WinForm“挂钩”到 WCF 服务中的各种事件中?例如,用户直接与 WCF 服务通信,我希望我的 WinForm 客户端得到通知。我怎样才能知道用户何时使用 WCF 服务做了一些事情并让 WinForm 客户端接受呢?

【问题讨论】:

  • 我认为您应该尝试 WCF 全双工服务。但是您必须创建一些逻辑来审核操作并将它们传输到您的 winform 应用程序
  • 我不确定为什么使用 WCF 将允许您从另一个进程访问不可序列化的对象?
  • @ShoaibShaikh - 我是 WCF 的新手,但看着全双工,它似乎是用户和服务之间的合同。 WinForm客户端是第三方的,不直接调用WCF服务。
  • @hugh - 如果服务维护不可序列化的对象,那么其他进程可以与服务对话以访问该对象。除非您知道在进程之间共享对象的另一种方式?看起来 WCF 是一种流行的方式。

标签: c# winforms wcf process wcf-client


【解决方案1】:

实现您的目标的一种方法是在您的服务上实现回调合约。然后,您的 win-forms 应用程序将能够“订阅”在服务上触发的事件(例如对您的对象的修改)。

为此,您需要使用回调合约实现服务合约:

[ServiceContract]
public interface IMyService_Callback
{
    [OperationContract(IsOneWay = true)]
    void NotifyClients(string message);
}

[ServiceContract(CallbackContract = typeof(IMyService_Callback))]
public interface IMyService
{
    [OperationContract]
    bool Subscribe();
}

然后你实现你的服务:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MyService : IMyService
{
    private List<IMyService_Callback> callbacks;

    public MyService()
    {
        this.callbacks = new List<IMyService_Callback>();
    }

    private void CallClients(string message)
    {
        callbacks.ForEach(callback => callback.NotifyClients(message));
    }

    public bool Subscribe()
    {
        var callback = OperationContext.Current.GetCallbackChannel<IMyService_Callback>();

        if (!this.callbacks.Contains(callback))
        {
            this.callbacks.Add(callback);
        }

        // send a message back to the client
        CallClients("Added a new callback");

        return true;
    }
}

在你的winforms客户端中你只需要实现回调方法:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public partial class ServiceClient : Form, IMyService_Callback
{
    // Sync context for enabling callbacks
    SynchronizationContext uiSyncContext;

    public ServiceClient()
    {
        InitializeComponent(); //etc.

        uiSyncContext = SynchronizationContext.Current;

        // Create proxy and subscribe to receive callbacks
        var factory = new DuplexChannelFactory<IMyService>(typeof(ServiceClient), "NetTcpBinding_IMyService");
        var proxy = factory.CreateChannel(new InstanceContext(this));
        proxy.Subscribe();
    }

    // Implement callback method
    public void NotifyClients(string message)
    {
        // Tell form thread to update the message text field
        SendOrPostCallback callback = state => this.Log(message);

        uiSyncContext.Post(callback, "Callback");
    }

    // Just updates a form text field
    public void Log(string message)
    {
        this.txtLog.Text += Environment.NewLine + message;
    }
}    

服务配置:

<system.serviceModel>
  <services>
    <service name="TestService.MyService" behaviorConfiguration="Normal">
      <endpoint 
        address="net.tcp://localhost:8000/MyService" 
        contract="TestService.IMyService" 
        binding="netTcpBinding" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="Normal" >
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

客户端配置

<system.serviceModel>
  <client>
    <endpoint address="net.tcp://localhost:8000/MyService" 
              binding="netTcpBinding"
              contract="TestService.IMyService"
              name="NetTcpBinding_IMyService">
    </endpoint>
  </client>
</system.serviceModel>

【讨论】:

  • 谢谢,这是一个很好的答案。
  • 代码实际上并没有工作 - 将尽快更新工作代码。但一般模式是正确的。
  • 代码现在可以工作 - 必须在客户端用 DuplexChannelFactory 替换 ChannelFactory。
  • 谢谢,我只是在阅读:D 模式是关键方面,因为我可以通过谷歌搜索解决任何错误。非常感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多