// called by SqlConnection.RepairConnection which is a relatevly expensive way of repair inner connection // prior to execution of request, used from EnlistTransaction, EnlistDistributedTransaction and ChangeDatabase internal bool GetSessionAndReconnectIfNeeded(SqlConnection parent, int timeout = 0) { Debug.Assert(!ThreadHasParserLockForClose, "Cannot call this method if caller has parser lock"); if (ThreadHasParserLockForClose) { return false; // we cannot restore if we cannot release lock } _parserLock.Wait(canReleaseFromAnyThread: false); ThreadHasParserLockForClose = true; // In case of error, let the connection know that we already own the parser lock bool releaseConnectionLock = true; try { RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #endif //DEBUG Task reconnectTask = parent.ValidateAndReconnect(() => { ThreadHasParserLockForClose = false; _parserLock.Release(); releaseConnectionLock = false; }, timeout); if (reconnectTask != null) { AsyncHelper.WaitForCompletion(reconnectTask, timeout); return true; } return false; #if DEBUG } finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException) { DoomThisConnection(); throw; } catch (System.StackOverflowException) { DoomThisConnection(); throw; } catch (System.Threading.ThreadAbortException) { DoomThisConnection(); throw; } } finally { if (releaseConnectionLock) { ThreadHasParserLockForClose = false; _parserLock.Release(); } } }
// called by SqlConnection.RepairConnection which is a relatevly expensive way of repair inner connection // prior to execution of request, used from EnlistTransaction, EnlistDistributedTransaction and ChangeDatabase internal bool GetSessionAndReconnectIfNeeded(SqlConnection parent, int timeout = 0) { Debug.Assert(!ThreadHasParserLockForClose, "Cannot call this method if caller has parser lock"); if (ThreadHasParserLockForClose) { return false; // we cannot restore if we cannot release lock } _parserLock.Wait(canReleaseFromAnyThread: false); ThreadHasParserLockForClose = true; // In case of error, let the connection know that we already own the parser lock bool releaseConnectionLock = true; try { Task reconnectTask = parent.ValidateAndReconnect(() => { ThreadHasParserLockForClose = false; _parserLock.Release(); releaseConnectionLock = false; }, timeout); if (reconnectTask != null) { AsyncHelper.WaitForCompletion(reconnectTask, timeout); return true; } return false; } finally { if (releaseConnectionLock) { ThreadHasParserLockForClose = false; _parserLock.Release(); } } }