我有一个WCF服务
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IMonitorService
{
[OperationContract]
[FaultContract(typeof(MonitorFaultException))]
void StartMonitoring(MonitorRequest monitorRequest);
}
在服务实现中,我有以下服务行为
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
我有两个客户服务
如果是控制台应用程序客户端,一切正常。但是当我使用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 为什么异步版本的方法不起作用?