WCF服务进行回调时客户端的异常

时间:2018-02-09 14:31:46

标签: c# asp.net wcf asynchronous async-await

我有一个WCF服务

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IMonitorService
{
  [OperationContract]
  [FaultContract(typeof(MonitorFaultException))]
  void StartMonitoring(MonitorRequest monitorRequest);

}

在服务实现中,我有以下服务行为

  

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]

我有两个客户服务

  1. 控制台应用程序(用于测试)。
  2. Web应用程序REST API。
  3. 如果是控制台应用程序客户端,一切正常。但是当我使用Web应用程序客户端并且从服务端有回调时,我得到以下错误:

      

    此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async =" true" %GT;

    我的网络应用程序控制器看起来像

    // I am using same types as WCF for input just for simplicity
    public ApiResponse StartMonitor(MonitorRequest request)
    {
       IMonitorService monitorService = new MonitorServiceClient(new InstanceContext(callbackEventHandler));
       monitorService.StartMonitoring(request);
    
       //create ApiResponse and return.
    }
    

    控制台应用程序也具有与上面显示的相同的代码。唯一的区别是我在Console.Read()的末尾有一个main

    以下是来自Windows事件查看器的堆栈跟踪

      

    StackTrace:at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&安培;   rpc)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&安培;   rpc)at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean   isOperationContextSet)at   System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(的RequestContext   request,Boolean cleanThread,OperationContext   currentOperationContext)at   System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(的RequestContext   请求,OperationContext currentOperationContext)at   System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult的   结果)在   System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.ServiceModel.Channels.TransportDuplexSessionChannel.TryReceiveAsyncResult.OnReceive(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.OnReceiveComplete(对象   国家)   System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(对象   国家)   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   结果)在System.Net.LazyAsyncResult.Complete(IntPtr userToken)
      在System.Net.LazyAsyncResult.ProtectedInvokeCallback(对象结果,   IntPtr userToken)at   System.Net.Security.NegotiateStream.ProcessFrameBody(Int32 readBytes,   Byte []缓冲区,Int32偏移量,Int32计数,AsyncProtocolRequest   asyncRequest)at   System.Net.Security.NegotiateStream.ReadCallback(AsyncProtocolRequest   asyncRequest)at   System.Net.AsyncProtocolRequest.CompleteRequest(Int32 result)at   System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(Int32 bytes)   在System.Net.FixedSizeReader.ReadCallback(IAsyncResult   transportRestime。在System.Runtime.AsyncResult.Complete(Boolean   完成同步)   System.ServiceModel.Channels.ConnectionStream.IOAsyncResult.OnAsyncIOComplete(对象   国家)   System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(的SocketAsyncEventArgs   吃   System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(SocketError   socketError,Int32 bytesTransferred,SocketFlags flags)at   System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32的   errorCode,UInt32 numBytes,NativeOverlapped * nativeOverlapped)at   System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32的   errorCode,UInt32 numBytes,NativeOverlapped * pOVERLAP)

         

    InnerException:System.InvalidOperationException

    但是当我在一个单独的线程上调用该服务时,一切都开始正常工作: -

    更改

      monitorService.StartMonitoring(request)
    

      Task.Run(() => monitorService.StartMonitoring(request)).Wait();
    

    我也尝试调用异步版本(通过相应地更改控制器的返回类型)

     await monitorService.StartMonitoringAsync(request);
    

    但随后错误消息将更改为:

      

    在异步操作仍处于挂起状态时完成异步模块或处理程序。

    编辑上述错误不在回调中,但是以ApiResponse的形式出现。

    我有以下问题: -

    Q-1 为什么控制台客户端回调正在发生且Web应用程序回调没有发生?我猜Console.Read()(我在控制台应用程序中正在做的)是让线程等待接收回调。请澄清。

    Q-2 为什么当我在单独的线程上拨打电话时,网络应用程序上会发生回调?

    Q-3编辑:新问题一般来说,哪个线程回调来自WCF服务?它是客户端的新线程,每次都能处理回调吗?

    Q-4 为什么异步版本的方法不起作用?

0 个答案:

没有答案