ReportViewer在设计报告参数(SetParameter)时线程挂起(hang)
I have a web application use Microsoft ReportViewer(2012) to show report. I use LocalReport and normal DataTable to provide datasource. And the DataTable fill by ODP.NET. When i run one report everything is ok, but when i run two report at same time, one of report just wait until the another finish ODP.NET query, and then two report render. I do some debugging on it, but i can't find the solution. below are debug info
Thread 12
Current frame:
ChildEBP RetAddr Caller, Callee
04ddc8d8 0f3b0879 (MethodDesc 0f058288 +0x49 Microsoft.ReportingServices.ReportIntermediateFormat.Persistence.IntermediateFormatWriter.Write(Microsoft.ReportingServices.ReportIntermediateFormat.Persistence.IPersistable, Boolean))
04ddca2c 65926597 (MethodDesc 65180214 +0x27 System.Runtime.Remoting.ObjRef.GetServerDomainId())
04ddca50 6527da33 (MethodDesc 650df0ec +0x47 System.AppDomain.Unload(System.AppDomain))
04ddca7c 0ed9fec2 (MethodDesc 006d5690 +0x132 Microsoft.Reporting.ReportCompiler.CompileReport(Microsoft.ReportingServices.Diagnostics.ICatalogItemContext, Byte[], Boolean, Microsoft.ReportingServices.Library.ControlSnapshot ByRef))
04ddcaa4 0ed9fbd0 (MethodDesc 0edafbb8 +0x20 Microsoft.Reporting.ReportRuntimeSetupHandler.GetReportRuntimeSetup())
04ddcab8 0ed9f76a (MethodDesc 0edaede8 +0xea Microsoft.Reporting.LocalService.GetCompiledReport(Microsoft.Reporting.PreviewItemContext, Boolean, Microsoft.ReportingServices.Library.ControlSnapshot ByRef))
04ddcb00 65311c03 (MethodDesc 650e1b18 +0xe3 System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon))
04ddcb14 0ed9f62e (MethodDesc 0edaee04 +0x1e Microsoft.Reporting.LocalService.CompileReport())
04ddcb30 0ed9f5f6 (MethodDesc 0edaedf4 +0x6 Microsoft.Reporting.LocalService.Microsoft.Reporting.ILocalProcessingHost.CompileReport())
04ddcb34 0ed9f535 (MethodDesc 0eda8f2c +0x45 Microsoft.Reporting.WebForms.LocalReport.EnsureExecutionSession())
04ddcb64 0ed9f487 (MethodDesc 0eda8f60 +0x37 Microsoft.Reporting.WebForms.LocalReport.GetParameters())
04ddcb94 0f39a67d (MethodDesc 006b82ac +0xad XRisk.BLL.Report.RenderReport.processParameter())
04ddcbbc 0ea05c11 (MethodDesc 03fd7c94 +0x71 XRisk.BLL.Report.ReportEntity.get_SubReportCodeList())
04ddcbd0 03ef07fb (MethodDesc 03f00a3c +0x2b XRisk.PCL.Utility.LogHelper.Info(System.Object))
04ddcbe0 0f39a3fb (MethodDesc 006b8294 +0x4db XRisk.BLL.Report.RenderReport.LoadReport())
04ddcc04 03eff56a (MethodDesc 03fdb4ac +0x6a XRisk.BLL.BusinessEntityListProvider.XRisk.BLL.IEntityListProvider.Execute[[System.__Canon, mscorlib]](XRisk.BLL.CacheMode, System.String, System.Object[]))
04ddccd4 0f399e0d (MethodDesc 006b8288 +0xcd XRisk.BLL.Report.RenderReport.Render(XRisk.BLL.Report.RenderFormat))
04ddcce0 6531091a (MethodDesc 650e1b28 +0x13a System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].Insert(System.__Canon, System.__Canon, Boolean))
04ddcce4 65310a92 (MethodDesc 650e1c50 +0x12 System.Collections.Generic.EqualityComparer`1[[System.__Canon, mscorlib]].get_Default())
04ddcce8 0f399ce2 (MethodDesc 006b8258 +0xc2 XRisk.BLL.Report.RenderReport..ctor(Microsoft.Reporting.WebForms.LocalReport, System.String, System.Collections.Generic.Dictionary`2<System.String,System.String>, System.Data.DataSet, Int32, System.Collections.Generic.IDictionary`2<System.String,System.String>))
04ddcd14 0f3996be (MethodDesc 006b7078 +0x4de XRisk.Web.Report.ReportViewRdlc.SetReport())
04ddcd48 03ef07fb (MethodDesc 03f00a3c +0x2b XRisk.PCL.Utility.LogHelper.Info(System.Object))
04ddcd58 0f39917b (MethodDesc 0eb45794 +0x3eb XRisk.Web.SessionHelper.ClearReportViewerCache(System.Web.SessionState.HttpSessionState, System.String))
04ddce24 0f398ceb (MethodDesc 006b7048 +0xab XRisk.Web.Report.ReportViewRdlc.Page_Load(System.Object, System.EventArgs))
another thread.
Thread 27
Current frame:
ChildEBP RetAddr Caller, Callee
0e9fd838 0c3b906d (MethodDesc 0c02a8f0 +0x37d Oracle.DataAccess.Client.OracleDataReader.GetString(Int32))
0e9fe168 0c0f07d1 (MethodDesc 0c02eab8 +0x181 DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, IntPtr ByRef, IntPtr ByRef, IntPtr ByRef, IntPtr ByRef, IntPtr, Int32 ByRef, Int32, Int32, Int64 ByRef, Oracle.DataAccess.Client.OpoSqlValCtx* ByRef, System.String, Oracle.DataAccess.Client.OpoDacValCtx* ByRef, IntPtr[], System.String[], Oracle.DataAccess.Client.OpoMetValCtx* ByRef, Int32))
0e9fe1dc 0c0f07d1 (MethodDesc 0c02eab8 +0x181 DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, IntPtr ByRef, IntPtr ByRef, IntPtr ByRef, IntPtr ByRef, IntPtr, Int32 ByRef, Int32, Int32, Int64 ByRef, Oracle.DataAccess.Client.OpoSqlValCtx* ByRef, System.String, Oracle.DataAccess.Client.OpoDacValCtx* ByRef, IntPtr[], System.String[], Oracle.DataAccess.Client.OpoMetValCtx* ByRef, Int32))
0e9fe26c 0c13cc4f (MethodDesc 0c026010 +0xdaf Oracle.DataAccess.Client.OracleCommand.ExecuteReader(Boolean, Boolean, System.Data.CommandBehavior))
0e9fe45c 0c13988c (MethodDesc 0c0266a4 +0xcc Oracle.DataAccess.Client.OracleDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior))
0e9fe4ac 5574b35f (MethodDesc 5568f994 +0x5f System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet))
0e9fe4f0 04487cbe (MethodDesc 03fde7fc +0xbe XRisk.DAL.Oracle.ODPOracleHelper.ExecuteDataSet(System.String, XRisk.DAL.Oracle.ODPCommandItem, Oracle.DataAccess.Client.OracleConnection))
0e9fe548 04485f63 (MethodDesc 03fddf6c +0xe3 XRisk.DAL.Oracle.ODPProcCommand.ExecuteDataSet(XRisk.DAL.ContentTemplate, Oracle.DataAccess.Client.OracleConnection))
0e9fe5f4 0561cc2c (MethodDesc 03f1f784 +0x1c Oracle.DataAccess.Client.OracleConnection.set_TxnHndAllocated(Int32))
0e9fe694 04482d5d (MethodDesc 03fddf40 +0x24d XRisk.DAL.Oracle.ODPProcCommand.ForProcTran())
0e9fe7d0 0448b67a (MethodDesc 03fdad54 +0x7a XRisk.DAL.Oracle.OracleProcService.GetData(XRisk.DAL.ProcTemplate))
0e9fe80c 0dee0c80 (MethodDesc 03fdad28 +0x40 XRisk.DAL.Oracle.OracleProcService.GetData(System.String, XRisk.DAL.ParamPair[]))
0e9fe82c 006a931e (MethodDesc 0eb4e280 +0x55e XRisk.BLL.Task.ProcCalcTask.DoExecute())
0e9fe850 03efd524 (MethodDesc 03f07038 +0xb4 log4net.Repository.Hierarchy.Logger.CallAppenders(log4net.Core.LoggingEvent))
0e9fe88c 03efd3da (MethodDesc 03f07050 +0x4a log4net.Repository.Hierarchy.Logger.ForcedLog(System.Type, log4net.Core.Level, System.Object, System.Exception))
0e9fe8a0 03efd153 (MethodDesc 03f07018 +0x63 log4net.Repository.Hierarchy.Logger.Log(System.Type, log4net.Core.Level, System.Object, System.Exception))
0e9fe8d4 03ef0990 (MethodDesc 03f00a78 +0x170 XRisk.PCL.Utility.LogHelper.Log(System.Object, log4net.Core.Level, System.String))
0e9fea1c 0ec85896 (MethodDesc 04e04ab4 +0xa6 XRisk.BLL.Task.TaskBase.Execute())
0e9fea7c 0dee41de (MethodDesc 04e00538 +0x18e XRisk.BLL.Task.TaskService.ExecWebTask())
0e9feb60 6530b30b (MethodDesc 6514e550 +0x63 System.Threading.ThreadHelper.ThreadStart_Context(System.Object))
0e9feb70 65298004 (MethodDesc 650d75f4 +0xb0 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean))
0e9feb8c 65297f44 (MethodDesc 650d75e8 +0x2c System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object))
0e9febac 6530b298 (MethodDesc 650c86cc +0x44 System.Threading.ThreadHelper.ThreadStart())
and thread state:
0:012> !threadstate 3009220
Legal to Join
Background
CLR Owns
In Multi Threaded Apartment
Thread Pool Worker Thread
Interruptible
0:012> !threadstate b020
Legal to Join
CLR Owns
CoInitialized
In Multi Threaded Apartment
I think i figure out it. I have a OracleClob input parameter to call thre oracle store procedure and i set the parameter like this:
OracleClob tempLob = new OracleClob(connection);
{
byte[] tempbuff = Encoding.Unicode.GetBytes((string)paramValue);
tempLob.BeginChunkWrite();
tempLob.Write(tempbuff, 0, tempbuff.Length);
tempLob.EndChunkWrite();
}
parameter.Value = tempLob;
The problem is i don't dispose tempLob manual, just let GC Finalizer do. On the other hand, when reportviewer try to set or get parameter, she compile report first like the quest first clr stack show. reportviewer create a temp AppDomain to compile report, after compile, this AppDomain just unloaded. So when unloading AppDomain, the clr suspend all threads and find the related threads to that AppDomain... finally GC called,so object's Finalize method called too. When OracleClob's Finalize called, it's enter a CriticalSection to free memory. But right now other thread is Execute ODP.NET query and waiting result, it's in CriticalSection too, do the finalize method waiting until the query finish. The phenomenon just like the question show. here are more debug info: finalize thread's native stack.
ChildEBP RetAddr Args to Child
03b7bf90 77505b0c 774ef98e 00000d8c 00000000 ntdll!KiFastSystemCallRet
03b7bf94 774ef98e 00000d8c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
03b7bff8 774ef872 00000000 00000000 1be57ed8 ntdll!RtlpWaitOnCriticalSection+0x13e
03b7c020 1017a2fc 1be30208 00000000 03b7e6a4 ntdll!RtlEnterCriticalSection+0x150
WARNING: Stack unwind information not available. Following frames may be wrong.
03b7c030 10ac9401 0e291b50 1be8bdd4 00000000 OraOCIEI11!sltsmna+0x1c
03b7e6a4 10a0ab07 1be8bdb4 1bf37474 1bffaf24 OraOCIEI11!kpulunli+0x30d27
03b7e6bc 1003c9fe 1be8bdb4 1bf37474 1bffaf24 OraOCIEI11!OCILobFreeTemporary+0x15
03b7f10c 0e1aa189 1be8bdb4 1bf37474 1bffaf24 OCI!OCILobFreeTemporary+0x32
03b7f1d0 70d65b65 03b7f21c 70ddf1ac 03b7f3e8 OraOps11w!OpsLobFreeTemporary+0xe9
03b7f22c 70d65a2b 1cd62458 0f2ccb20 00000000 clr!MethodTable::SetObjCreateDelegate+0xbd
03b7f258 70d65aba 1cd62458 1cd62458 00000000 clr!MethodTable::CallFinalizer+0xca
03b7f270 70d65cff 1cd62458 3e10c1b3 03b7f2e0 clr!WKS::CallFinalizer+0xa7
03b7f2c0 70d65c3b 00509630 00000804 03b7f2ef clr!WKS::GCHeap::TraceGCSegments+0x239
03b7f2f0 70ea8962 00509630 00000000 03b7f710 clr!WKS::GCHeap::TraceGCSegments+0x415
03b7f304 70e7f1e3 03b7f57c 03b7f3e8 00509630 clr!WKS::ProfScanRootsHelper+0x6b
03b7f318 70e7f265 03b7f710 3e10c0bb 03b7f710 clr!Thread::DoExtraWorkForFinalizer+0x114
03b7f3c8 70e7f320 03b7f710 3e10c75b 00509630 clr!Thread::ShouldChangeAbortToUnload+0x101
03b7f428 70e7f895 005a8a38 03b7f50c 70ff7a62 clr!Thread::ShouldChangeAbortToUnload+0x399
03b7f434 70ff7a62 03b7f710 3e10c67f 00509630 clr!Thread::RaiseCrossContextException+0x3f8
03b7f50c 70e4cc40 005ac5c0 70e7f87e 03b7f710 clr!Thread::DoADCallBack+0x33a
03b7f530 70e4cb72 03b7f710 03b7f598 70ea89d7 clr!Thread::DoExtraWorkForFinalizer+0x10c
03b7f53c 70ea89d7 005ac5c0 70ea8947 03b7f57c clr!ManagedThreadBase::FinalizerAppDomain+0x27
03b7f598 70d65c3b 00509630 00000000 03b7f5c7 clr!WKS::GCHeap::TraceGCSegments+0x2e3
03b7f5c8 70dfe3cf 00509630 00000000 00509630 clr!WKS::GCHeap::TraceGCSegments+0x415
03b7f5e4 70e7f1e3 00000001 03b7f6c8 00509630 clr!WKS::GCHeap::FinalizerThreadWorker+0xcd
03b7f5f8 70e7f265 03b7f710 3e10c5db 03b7f710 clr!Thread::DoExtraWorkForFinalizer+0x114
03b7f6a8 70e7f320 03b7f710 3e10c47b 00000000 clr!Thread::ShouldChangeAbortToUnload+0x101
03b7f708 70df7b8b 00000000 005ac5c0 00000000 clr!Thread::ShouldChangeAbortToUnload+0x399
03b7f72c 70df7b9e 70dfe31e 00000008 03b7f774 clr!ManagedThreadBase_NoADTransition+0x35
03b7f73c 70e8c8c0 70dfe31e 3e10c407 00000000 clr!ManagedThreadBase::FinalizerBase+0xf
03b7f774 70d62bb0 00000000 00000000 00000000 clr!WKS::GCHeap::FinalizerThreadStart+0x10c
03b7f818 75dc1114 004ecef8 03b7f864 7751b299 clr!Thread::intermediateThreadProc+0x4b
03b7f824 7751b299 004ecef8 74c92c3d 00000000 KERNEL32!BaseThreadInitThunk+0xe
03b7f864 7751b26c 70d62b68 004ecef8 00000000 ntdll!__RtlUserThreadStart+0x70
03b7f87c 00000000 70d62b68 004ecef8 00000000 ntdll!_RtlUserThreadStart+0x1b
other thread execute query:
ChildEBP RetAddr Args to Child
182e7db0 77505b0c 750a727f 00000e58 00000001 ntdll!KiFastSystemCallRet
182e7db4 750a727f 00000e58 00000001 182e7ddc ntdll!NtWaitForSingleObject+0xc
182e7df4 750ac5dc 00000e58 00000d64 00000002 mswsock!SockWaitForSingleObject+0x1ba
182e7e70 776bc308 00000d64 182e7ed0 00000001 mswsock!WSPRecv+0x2a7
182e7eac 10f4c913 00000d64 182e7ed0 00000001 ws2_32!WSARecv+0x7b
WARNING: Stack unwind information not available. Following frames may be wrong.
182e7ee8 113af2a9 00000d64 1be0258e 00000810 OraOCIEI11!lfvpos+0x5d0cb
182e7ff0 110ec403 1beaae48 1be0258e 00000810 OraOCIEI11!k2mdii+0x7dd9b
182e82cc 110ec963 1be9fc38 1be9fd54 182e8404 OraOCIEI11!nlnvgin+0x14b79b
182e82e8 110a7d7d 1be9fc38 1be9fd54 182e8404 OraOCIEI11!nlnvgin+0x14bcfb
182e8408 101deb5c 1be92734 00000000 1be9480a OraOCIEI11!nlnvgin+0x107115
182e8cc0 1114e174 1be947f8 00000000 1be8d8b0 OraOCIEI11!sigpidu+0x2aba
182e8cd8 1010aa6c 1be92734 00000000 101de6ea OraOCIEI11!nlnvgin+0x1ad50c
182eb004 10b0928d 1be92690 0000005e 1be946d8 OraOCIEI11!upicui2+0x652
182eb044 10b8484c 1be92690 0000005e 1be946d8 OraOCIEI11!upirtr+0x87
182eb07c 11ac8645 1be8bdb4 0000005e 1be946d8 OraOCIEI11!kpurcsc+0x5a
182ed408 10a09cc0 1be8bdb4 1bf1ed2c 1bf3c9f0 OraOCIEI11!sqlprct+0x33b4ed
182ed434 1007a25b 1be8bdb4 1bf1ed2c 1bf3c9f0 OraOCIEI11!OCIStmtExecute+0x24
182ede94 0e1b72bf 1be8bdb4 1bf1ed2c 1bf3c9f0 OCI!OCIStmtExecute+0x3f
182eded4 0e1ae444 0a498c18 1bf3c9f0 1bf1ed2c OraOps11w!OpsTxnDispose+0x6d7f
182edf58 0e1ae792 0a498c18 1bf3c9f0 1cea7f4c OraOps11w!OpsSqlPrepare2+0xf54
00000000 00000000 00000000 00000000 00000000 OraOps11w!OpsSqlExecuteReader+0x1b2
and locks:
0:024> !mlocks
Scanning for ReaderWriterLock instances...
Scanning for holders of ReaderWriterLock locks...
Scanning for ReaderWriterLockSlim instances...
Scanning for holders of ReaderWriterLockSlim locks...
Examining CriticalSections...
ClrThread DbgThread OsThread LockType Lock LockLevel
----------------------------------------------------------------------
0x14 24 0x1108 CritSect 1be30208
0x14 24 0x1108 CritSect 1be30238
0x14 24 0x1108 CritSect 1be4d530
0x1c 35 0x1138 thinlock 1cdb5f10 (recursion:0)
0x1c 35 0x1138 thinlock 1a23421c (recursion:0)
To fix it, i just set OracleClob input parameter like this,
最后是演示这上问题的Demo。/Files/jmax/CrashDemo.zip