我正在运行一个Windows服务,它正在对其他地方运行的多个其他WCF服务进行多次调用。有时我们的客户在调用端点时会遇到无法捕获的异常,从而导致我们的服务崩溃。端点的服务器端正在运行一个实例,除了它所进行的数据库调用之外,它实际上是完全无状态的。
例外是System.AccessViolationException'我所知道的属于腐败状态异常的范畴,正如我已经阅读here。
我知道[HandleProcessCorruptedStateExceptions]属性,以及使用它处理代码的所有警告,这些代码也不是由异常的捕获器维护的。
调用堆栈的顶部深入研究WCF包装的本机Windows库:
System.AccessViolationException Stack:
at System.Net.UnsafeNclNativeMethods+OSSOCK.recv(IntPtr, Byte*, Int32, System.Net.Sockets.SocketFlags)
at System.Net.Sockets.Socket.Receive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.Sockets.SocketError ByRef)
at System.Net.Sockets.Socket.Receive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[], Int32, Int32)
at System.Net.PooledStream.Read(Byte[], Int32, Int32)
at System.Net.Connection.SyncRead(System.Net.HttpWebRequest, Boolean, Boolean)
at System.Net.Connection.PollAndRead(System.Net.HttpWebRequest, Boolean)
at System.Net.ConnectStream.WriteHeaders(Boolean)
at System.Net.HttpWebRequest.EndSubmitRequest()
at System.Net.HttpWebRequest.SetRequestSubmitDone(System.Net.ConnectStream)
at System.Net.Connection.CompleteStartRequest(Boolean, System.Net.HttpWebRequest, System.Net.TriState)
at System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest, Boolean)
at System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)
at System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)
at System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
at System.Net.HttpWebRequest.GetRequestStream()
at System.ServiceModel.Channels.HttpOutput+WebRequestHttpOutput.GetOutputStream()
at System.ServiceModel.Channels.HttpOutput.Send(System.TimeSpan)
at System.ServiceModel.Channels.HttpChannelFactory`1+HttpRequestChannel+HttpChannelRequest[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SendRequest(System.ServiceModel.Channels.Message, System.TimeSpan)
at System.ServiceModel.Channels.RequestChannel.Request(System.ServiceModel.Channels.Message, System.TimeSpan)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message, System.TimeSpan)
at System.ServiceModel.Channels.ServiceChannel.Call(System.String, Boolean, System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[], System.TimeSpan)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage, System.ServiceModel.Dispatcher.ProxyOperationRuntime)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32)
at WCFCommunicator.IComEndpoint.TestEndpoint()
at WCFCommunicator.SendingLayer+<>c.<VerifyCurrentEndpoints>b__38_0(WCFCommunicator.IComEndpoint)
at WCFCommunicator.HttpWrapper.Client`2[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].UseCom[[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.Func`2<System.__Canon,Boolean>, ErrorType ByRef, System.String)
at WCFCommunicator.SendingLayer.VerifyCurrentEndpoints()
at WCFCommunicator.LocalSubscriptionAnalyzer.ValidateEndpoints_Elapsed(System.Object, System.Timers.ElapsedEventArgs)
at System.Timers.Timer.MyTimerCallback(System.Object)
at System.Threading.TimerQueueTimer.CallCallbackInContext(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.TimerQueueTimer.CallCallback() at System.Threading.TimerQueueTimer.Fire() at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback()
客户端代码总是作为lambda传入,并在try / catch / finally中执行,如下所示:
public TReturn UseCom<TReturn>(Func<Com, TReturn> code)
{
Com channel = cFactory.CreateChannel();
bool error = true;
try
{
TReturn result = code(channel);
((IClientChannel)channel).Close();
error = false;
return result;
}
catch (EndpointNotFoundException e)
{
//log and handle
return default(TReturn);
}
catch (FaultException e)
{
//log and handle
return default(TReturn);
}
catch (CommunicationException e)
{
//log and handle
return default(TReturn);
}
catch (Exception e)
{
//log and handle
return default(TReturn);
}
finally
{
if (error)
{
((IClientChannel)channel).Abort();
}
}
}
使用方法如下:
var result = clientInstance.UseCom(endpoint => endpoint.TestEndpoint());
此问题极难重现,似乎没有显示任何其他模式,任何帮助将不胜感激。