在很长一段时间里,我把系统服务作为WCF的宿主正式发布后,工作都很正常。知道一个比较单个功能函数耗时较多的服务发布后,经常会异常退出。很长一段时间里,我都认为是相应时间设置太短,一直客户端接受到异常。我好久时间里,都关注和改进这个函数的执行效率,以便于在更短时间内处理完毕。
一直到我看到了系统服务“事件日志”,有报错信息,才正确分析并找到错误点。因为我在调试的过程中,好长一段时间都是还没调试到错误,就报超时错误啦,一直不能找到错误点。
其中错误的详细如下
Application: *****.WCFService.WINHost.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at System.Data.Common.UnsafeNativeMethods+ICommandText.Execute(IntPtr, System.Guid ByRef, System.Data.OleDb.tagDBPARAMS, IntPtr ByRef, System.Object ByRef)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForMultpleResults(System.Data.OleDb.tagDBPARAMS, System.Object ByRef)
at System.Data.OleDb.OleDbCommand.ExecuteCommandText(System.Object ByRef)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(System.Data.CommandBehavior, System.Object ByRef)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(System.Data.CommandBehavior, System.String)
at System.Data.OleDb.OleDbCommand.ExecuteReader(System.Data.CommandBehavior)
at System.Data.OleDb.OleDbCommand.System.Data.IDbCommand.ExecuteReader(System.Data.CommandBehavior)
at System.Data.Common.DbDataAdapter.FillInternal(System.Data.DataSet, System.Data.DataTable[], Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
at System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)
at System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, System.String)
at SFC.BasicClass4.SFCOraHelp.boExecuteSql(System.String, System.String[], System.String, System.Data.DataSet)
at SFC.BasicClass4.SFCBasic.dsExecuteSql(System.String, System.String[], System.String)
at SFC.Buffernet.WCFService.Service.CBufferNet.GetFeederListOfLine(System.String, System.String, System.String)
at DynamicClass.SyncInvoke GetFeederListOfLine (System.Object, System.Object[], System.Object[])
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object, System.Object[], System.Object[] ByRef)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(System.ServiceModel.Dispatcher.MessageRpc ByRef)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, Boolean, System.ServiceModel.OperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult)
at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(System.IAsyncResult)
at System.Runtime.Fx+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)
at System.Runtime.AsyncResult.Complete(Boolean)
at System.Runtime.AsyncResult.Complete(Boolean, System.Exception)
at System.ServiceModel.Channels.FramingDuplexSessionChannel+TryReceiveAsyncResult.OnReceive(System.IAsyncResult)
at System.Runtime.Fx+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)
at System.Runtime.AsyncResult.Complete(Boolean)
at System.Runtime.AsyncResult.Complete(Boolean, System.Exception)
at System.ServiceModel.Channels.SynchronizedMessageSource+ReceiveAsyncResult.OnReceiveComplete(System.Object)
at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(System.Object)
at System.ServiceModel.Channels.SocketConnection.FinishRead()
at System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(Boolean, Int32, Int32)
at System.ServiceModel.Channels.OverlappedContext.CompleteCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
at System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
我仔细查找,找到了其中的函数GetFeederListOfLine,当我一眼看到这个函数的时候,我就知道是什么原因啦,肯定是数据库操作Sql语句的原因。
我仔细调试分析,找到原因。在Sql中要有不等的几个参数,当其中一个参数的值为空时,我写的处理函数就不会加在这个参数。前面的文章有介绍,在OleDb操作Oracle时,参数必须手动添加并赋值,我这里如果值是空,我写的处理函数就不会添加这个参数,致使报错。我在调试时,可以找到这个报错,也有Try处理过程,单在WCF中如果遇到这个问题,会直接退出,不会有任何报错。如果宿主是exe可执行程序,这个程序会直接退出,如果是系统服务,这个服务也会推出,但是状态显示时运行的,致使上面的运行按钮式可操作的,停止按钮式灰色的(正常运行后,运行按钮式灰色的,停止按钮式可操作的),但会在事件日志中记录这一异常错误。