【问题标题】:WCF client doesn't call asynchronous methodsWCF 客户端不调用异步方法
【发布时间】:2011-06-21 11:40:59
【问题描述】:

我在我的 WCF 服务中实现了以下接口

[ServiceContract]
public interface IPrepaidService
{

    [OperationContract]
    PrepaidSubscriberInfo GetSubscriberInfo(string ctn);

    [OperationContractAttribute(AsyncPattern = true)]
    IAsyncResult BeginGetSubscriberInfo(string ctn, AsyncCallback cb, object state);
    PrepaidSubscriberInfo EndGetSubscriberInfo(IAsyncResult r);



}

这边

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class PrepaidService : IPrepaidService
{

        public PrepaidSubscriberInfo GetSubscriberInfo(string ctn)
        {

            PrepaidSubscriberInfo result = null;

            try
            {
        result = new PrepaidSubscriberInfo();
        ...

            }
            catch (Exception ex) { throw new Exception(ex.ToString(), ex); }
            return result;
        }

        public IAsyncResult BeginGetSubscriberInfo(string ctn, AsyncCallback cb, object state)
        {            
            Task<PrepaidSubscriberInfo> task = Task<PrepaidSubscriberInfo>.Factory.StartNew(_ => GetSubscriberInfo(ctn), state);
            if (cb != null) task.ContinueWith(res => cb(task));
            return task;
        }

        public PrepaidSubscriberInfo EndGetSubscriberInfo(IAsyncResult ar)
        {            
            return ((Task<PrepaidSubscriberInfo>)ar).Result;
        }
}

我生成了代理和配置文件:

c:\temp>svcutil http://localhost/Service.svc /async

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="MetadataExchangeHttpBinding_IPrepaidService" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
            allowCookies="false">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
              enabled="false" />
          <security mode="None">
            <transport clientCredentialType="Windows" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/Service.svc"
          binding="wsHttpBinding" bindingConfiguration="MetadataExchangeHttpBinding_IPrepaidService"
          contract="IPrepaidService" name="MetadataExchangeHttpBinding_IPrepaidService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

我正在尝试以这种方式在 WCF 客户端上调用异步方法

    static void Main(string[] args)
    {

        ChannelFactory<IPrepaidServiceChannel> factory = new ChannelFactory<IPrepaidServiceChannel>("MetadataExchangeHttpBinding_IPrepaidService");
        factory.Open();
        IPrepaidServiceChannel channelClient = factory.CreateChannel();

        IAsyncResult arAdd = channelClient.BeginGetSubscriberInfo("xxx", AddCallback, channelClient);

        IAsyncResult arAdd2 = channelClient.BeginGetSubscriberInfo("xxx", AddCallback, channelClient);

        IAsyncResult arAdd3 = channelClient.BeginGetSubscriberInfo("yyy", AddCallback, channelClient);

        IAsyncResult arAdd4 = channelClient.BeginGetSubscriberInfo("yyy", AddCallback, channelClient);
        Console.WriteLine("1");



        Console.ReadKey();

    }

    static void AddCallback(IAsyncResult ar)
    {
        var result = ((IPrepaidService)ar.AsyncState).EndGetSubscriberInfo(ar);
        Console.WriteLine("Result: {0}", result);
    }

但 WCF 客户端始终在 WCF 服务上调用 GetSubscriberInfo() 方法,而不是其异步版本 BeginGetSubscriberInfo 和 EndGetSubscriberInfo。当我删除 [OperationContract] PrepaidSubscriberInfo GetSubscriberInfo(string ctn); 客户端调用异步版本。

抱歉,格式错误,但我无法使用此 UI 进行管理

【问题讨论】:

  • “抱歉,格式错误,但我无法使用此 UI 进行管理”:选择代码并单击脚本块图标有这么难吗?
  • @Steve B. 我尝试这样做,但我的代码格式错误

标签: wcf c#-4.0 asynchronous


【解决方案1】:

客户端和服务可以独立执行/不执行异步。客户端调用异步仅仅意味着从客户端的角度来看调用是异步的,服务甚至不必支持异步

该服务更喜欢同步而不是异步,因此如果您希望您的服务被异步调用,请从其合同版本中删除同步版本

【讨论】:

  • 如果我想在我的合同中同时拥有这两个版本怎么办。例如这里 msdn.microsoft.com/en-us/library/ms731177.aspx 声明了两个版本
  • 中间有一条注释说“// 这个异步实现的操作永远不会被调用,因为有相同方法的同步版本。”。您必须决定如何最好地实现您的服务幻灯片功能 - 同步或异步。客户端可以独立调用服务异步或同步,但它与服务的调用方式无关 - 仅与代理的调用方式有关。如果两者都有,您将如何决定应该调用哪个版本?
猜你喜欢
  • 2012-10-03
  • 2013-11-21
  • 2013-03-10
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
相关资源
最近更新 更多