我正面临一些“不可能的行为”的情况,我需要以某种方式对其进行调试。
我有两个线程,A 和 B。线程 B 类有这三个变量:
public class ThreadBClass() {
private static bool shouldStop = false;
private static objects shouldStopLock = new object();
public static void SetShouldStop()
{
lock( shouldStopLock ) {
shouldStop = true;
}
}
public void Run()
{
while( true ) {
lock( shouldStopLock ) {
if( shouldStop ) {
break;
}
}
doStuff(); << this thing queries SQL Azure database
}
}
}
线程 A 有这个
var bClass = new threadBClass();
var controlledThread = new Thread( bClass.Run );
线程 BRun()
以无限循环运行,定期查询 SQL Azure 数据库。
现在这两个线程在 Windows Azure Web 角色中运行,当角色停止时会发生以下情况。角色OnStop()
在线程 A 中运行并执行以下操作:
ThreadBClass.SetShouldStop();
const int count = 20;
for( int i = 0; i < count; i++ ) {
if( controlledThread.IsAlive ) {
break;
}
Thread.Sleep( 1000 );
}
如果在设置标志时线程 B 碰巧没有查询数据库,那么一切都会干净地退出。但是大约 40% 的情况下 SQL 数据库查询会失败,但以下情况除外:
System.Data.SqlClient.SqlException
Timeout expired. The timeout period elapsed prior to completion of
the operation or the server is not responding.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName)
at System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso, String transactionName)
//my code of Run() here
我试过输出ThreadState
每个线程的。线程 B 的状态是Running
,所以它肯定没有中止。
所以整个情况对我来说看起来很疯狂 - 一个线程获得了一段时间的锁,然后轮询另一个线程,IsAlive
并且恰好在那个时候 SQL 查询在另一个线程中超时。而且这是偶尔可以重现的。
我该如何调试?是否有任何事件、全局变量以及 .NET 运行时公开的任何其他内容,并且我可以使用它们来查找实际发生的情况?