我需要采取哪些步骤才能使用 WCF 回调?

Posted

技术标签:

【中文标题】我需要采取哪些步骤才能使用 WCF 回调?【英文标题】:What steps do I need to take to use WCF Callbacks? 【发布时间】:2010-11-05 20:41:35 【问题描述】:

我正在努力学习 WCF。我有一个简单的客户端和服务器应用程序设置,按下客户端上的按钮后,它会从服务器获取更新的值。

我的下一步是尝试从服务器到客户端进行回调以更新其值。我已经列举了很多例子,它们看起来太大而且令人困惑。有没有人可以给出我在 C# 中实现的最简单示例?

我一直在网上浏览示例,但我只是不明白它需要什么?当然,我可以逐行复制示例,但这对我没有好处,因为如果我想在自己的代码中执行此操作,我仍然不知道要实现什么。

有人可以帮我举一个非常简单的例子,说明我需要采取哪些步骤,以及我需要在服务器代码和客户端代码中做什么才能实现这一点?

谢谢

【问题讨论】:

【参考方案1】:

这是我能想到的最简单的完整示例:

public interface IMyContractCallback

    [OperationContract]
    void OnCallback();


[ServiceContract(CallbackContract = typeof(IMyContractCallback))]
public interface IMyContract

    [OperationContract]
    void DoSomething();


[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MyService : IMyContract

    public void DoSomething()
    
        Console.WriteLine("Hi from server!");
        var callback = OperationContext.Current.GetCallbackChannel<IMyContractCallback>();
        callback.OnCallback();
    


public class MyContractClient : DuplexClientBase<IMyContract>

    public MyContractClient(object callbackInstance, Binding binding, EndpointAddress remoteAddress)
        : base(callbackInstance, binding, remoteAddress)  


public class MyCallbackClient : IMyContractCallback

    public void OnCallback()
    
        Console.WriteLine("Hi from client!");
    


class Program

    static void Main(string[] args)
    
        var uri = new Uri("net.tcp://localhost");
        var binding = new NetTcpBinding();
        var host = new ServiceHost(typeof(MyService), uri);
        host.AddServiceEndpoint(typeof(IMyContract), binding, "");
        host.Open();

        var callback = new MyCallbackClient();
        var client = new MyContractClient(callback, binding, new EndpointAddress(uri));
        var proxy = client.ChannelFactory.CreateChannel();
        proxy.DoSomething();
        // Printed in console:
        //  Hi from server!
        //  Hi from client!

        client.Close();
        host.Close();
    

为了运行示例,需要包含一些命名空间:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

【讨论】:

我还是觉得太难了。我将通过套接字实现:P 复制/粘贴此解决方案对我不起作用(VS2010,.NET 4.0)。客户端将阻塞等待服务器响应,您将获得超时异常。您必须将 [OperationContract(IsOneWay=true)] 放在 DoSomething 上。或者,您可以自己处理线程或在 MyCallbackClient 上设置 ConcurrencyMode=Multiple、UseSynchronizationContext=false。请参阅此问题/答案:***.com/a/13091230/2184185 这是我在尝试学习 WCF 中的双工通信时发现的最有用的东西。 我想知道为什么要添加 ConcurrencyMode.Reentrant。没有它,服务端会出现异常:“在 mscorlib.dll 中发生‘System.InvalidOperationException’类型的异常,但未在用户代码中处理附加信息:此操作将死锁,因为直到收到回复才能收到当前消息完成处理。如果要允许乱序消息处理,请在 ServiceBehaviorAttribute 上指定 Reentrant 或 Multiple 的 ConcurrencyMode。"【参考方案2】:

获取 Juval Lowy 的“Programming WCF Services, 2nd Edition”的副本。本书有很大一部分专门讨论回调操作。在第 5 章,从第 214 页开始。在有关并发管理的章节(第 8 章)中,还有更多信息。

“编程 WCF 服务”或多或少是 WCF 的“圣经”。

【讨论】:

【参考方案3】:

我知道,老问题......我今天早些时候从谷歌搜索中遇到了这个问题,Ray Vernagus 提供的答案是我迄今为止阅读过的最容易理解的 WCF 示例。如此之多,以至于我能够在不使用任何在线转换器的情况下在 VB.NET 中重写它。我想我会添加 Ray Vernagus 提供的示例的 VB.NET 变体。只需创建一个新的 VB.NET Windows 控制台应用程序,添加对 System.ServiceModel 的引用,然后将下面的整个代码复制/粘贴到默认的 Module1 类文件中。

Imports System.ServiceModel
Imports System.ServiceModel.Channels



Public Interface IMyContractCallback
    <OperationContract()> _
    Sub OnCallBack()
End Interface

<ServiceContract(CallBackContract:=GetType(IMyContractCallback))> _
Public Interface IMyContract
    <OperationContract()> _
    Sub DoSomething()
End Interface

<ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Reentrant)> _
Public Class Myservice
    Implements IMyContract

    Public Sub DoSomething() Implements IMyContract.DoSomething
        Console.WriteLine("Hi from server!")
        Dim callback As IMyContractCallback = OperationContext.Current.GetCallbackChannel(Of IMyContractCallback)()
        callback.OnCallBack()
    End Sub
End Class

Public Class MyContractClient
    Inherits DuplexClientBase(Of IMyContract)

    Public Sub New(ByVal callbackinstance As Object, ByVal binding As Binding, ByVal remoteAddress As EndpointAddress)
        MyBase.New(callbackinstance, binding, remoteAddress)
    End Sub
End Class

Public Class MyCallbackClient
    Implements IMyContractCallback

    Public Sub OnCallBack() Implements IMyContractCallback.OnCallBack
        Console.WriteLine("Hi from client!")
    End Sub
End Class


Module Module1

    Sub Main()
        Dim uri As New Uri("net.tcp://localhost")
        Dim binding As New NetTcpBinding()
        Dim host As New ServiceHost(GetType(Myservice), uri)
        host.AddServiceEndpoint(GetType(IMyContract), binding, "")
        host.Open()

        Dim callback As New MyCallbackClient()
        Dim client As New MyContractClient(callback, binding, New EndpointAddress(uri))
        Dim proxy As IMyContract = client.ChannelFactory.CreateChannel()

        proxy.DoSomething()
        ' Printed in console:
        '  Hi from server!
        '  Hi from client!

        Console.ReadLine()

        client.Close()
        host.Close()
    End Sub

End Module

【讨论】:

【参考方案4】:

如果我没看错您的问题,您希望在客户端和服务器之间进行双向对话(服务器可以与客户端进行通信)。 WSDualHttpBinding 为您提供此功能。

WCF 的不幸现实是没有简单的例子。它要求您定义合同、配置服务、使用主机并创建客户端代码。看看this article 有一个简单的例子。

【讨论】:

以上是关于我需要采取哪些步骤才能使用 WCF 回调?的主要内容,如果未能解决你的问题,请参考以下文章

您需要采取哪些步骤将 UIPanGestureRecognizer 触摸转换为 ScrollView 缩放?

WCF 服务证书认证

作为使用 Kivy 2.0 的初学者,我需要采取哪些步骤将我的项目(应用程序)编译到 Play 商店

响应式 WCF 客户端的双工回调或客户端线程

PCI合规的成本?

设置 SSL 以在 Azure 上使用 WCF 的步骤是啥?