0

我正面临一些“不可能的行为”的情况,我需要以某种方式对其进行调试。

我有两个线程,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 运行时公开的任何其他内容,并且我可以使用它们来查找实际发生的情况?

4

0 回答 0