我们有一个WCF服务,可以在网络文件存储(共享文件夹)上读写文档。 偶尔我们会看到线程开始陷入Win32Native代码的情况。线程被阻止后,所有后续调用也会被阻止。有趣的是,Windows服务重启后问题不会消失。第一个尝试使用文档存储块的线程,问题重复。只有在服务器重新启动后,服务才能继续工作一段时间(有时几天,有时几周)。
这只发生在我们的生产环境中。我目前没有关于发生问题时服务器状态的任何信息,关于任何备份进程或当时的任何Windows事件日志。 所以关于在哪里寻找以及可能导致这个问题的任何想法都会非常有用。
线程被阻止的代码示例是在文档存储上创建空文件时:
public void CreateFile( string filePath )
{
using ( FileStream stream = File.Create( filePath ) )
{
}
}
阻塞线程堆栈跟踪:
at Microsoft.Win32.Win32Native.CreateFile(String lpFileName, Int32 dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile)
at Microsoft.Win32.Win32Native.CreateFile(String lpFileName, Int32 dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile)
at Microsoft.Win32.Win32Native.SafeCreateFile(String lpFileName, Int32 dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
at MyService.DocumentProcessingComponent.CreateFile(string filePath)
. . . Custom Code . . .
at MyService.Service.DoSomething(Message requestMessage)
at SyncInvokeInvokeService(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(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 request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.Channels.TransportDuplexSessionChannel.TryReceiveAsyncResult.OnReceive(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.OnReceiveComplete(Object state)
at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(Object state)
at System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs)
at 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)
有时线程会在不同的Win32Native方法中被阻塞,如下例所示:
public ReadFileResult ReadFileBlock( string filePath, int blockIndex )
{
if ( !File.Exists( filePath ) )
return new ReadFileResult() { Error = "File not found" };
byte[] content = null;
int nextBlockIndex = 0;
using ( FileStream fs = File.Open( filePath, FileMode.Open, FileAccess.Read, FileShare.Read ) )
{
int offset = _defaultBlockSize * blockIndex;
if ( offset >= fs.Length )
return new ReadFileResult() { Error = "Block index out of range" };
fs.Seek( offset, SeekOrigin.Begin );
int bytesToRead = ( int )Math.Min( _defaultBlockSize, fs.Length - fs.Position );
content = new byte[ bytesToRead ];
int bytesRead = fs.Read( content, 0, bytesToRead );
if ( bytesRead < _defaultBlockSize || fs.Position == fs.Length )
nextBlockIndex = -1;
else
nextBlockIndex = blockIndex + 1;
}
return new ReadFileResult() { Block = content, NextBlockIndex = nextBlockIndex };
}
阻塞线程堆栈跟踪:
at Microsoft.Win32.Win32Native.GetFileAttributesEx(String name, Int32 fileInfoLevel, WIN32_FILE_ATTRIBUTE_DATA& lpFileInformation)
at Microsoft.Win32.Win32Native.GetFileAttributesEx(String name, Int32 fileInfoLevel, WIN32_FILE_ATTRIBUTE_DATA& lpFileInformation)
at System.IO.File.FillAttributeInfo(String path, WIN32_FILE_ATTRIBUTE_DATA& data, Boolean tryagain, Boolean returnErrorOnNotFound)
at System.IO.File.InternalExists(String path)
at System.IO.File.InternalExistsHelper(String path, Boolean checkHost)
at MyService.DocumentProcessingComponent.ReadFileBlock(string filePath, int blockIndex)