C# 如何调试由另一个线程中的操作触发的SQL查询超时?
我面临一些“不可能的行为”的情况,我需要以某种方式调试它 我有两个线程,A和B。线程B类有以下三个变量:C# 如何调试由另一个线程中的操作触发的SQL查询超时?,c#,.net,multithreading,azure,concurrency,C#,.net,Multithreading,Azure,Concurrency,我面临一些“不可能的行为”的情况,我需要以某种方式调试它 我有两个线程,A和B。线程B类有以下三个变量: public class ThreadBClass() { private static bool shouldStop = false; private static objects shouldStopLock = new object(); public static void SetShouldStop() { lock( should
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
}
}
}
线程B以无限循环运行Run()
,定期查询SQL Azure数据库
现在,这两个线程在WindowsAzure web角色内运行,当角色停止时,会发生以下情况。角色OnStop()
在线程A中运行,并执行以下操作:
ThreadBClass.SetShouldStop();
const int count = 20;
for( int i = 0; i < count; i++ ) {
if( controlledThread.IsAlive ) {
break;
}
Thread.Sleep( 1000 );
}
我已经尝试输出每个线程的ThreadState
。线程B的状态是正在运行
,因此它肯定没有被中止
所以在我看来,整个情况都很疯狂——一个线程获得了一个锁一段时间,然后轮询另一个线程的IsAlive
,而恰好在那个时候,SQL查询在另一个线程中超时。这是可以偶尔复制的
如何调试这个?是否有任何事件、全局变量以及.NET运行时公开的任何其他内容,我可以用来查找实际发生的情况?是什么引发了“角色被停止”?在我看来,这与锁/检查无关,而是与正在发生的其他事情有关;可能子系统本身正在关闭外部连接,因为它知道角色正在关闭。在锁内设置值不会导致TDS错误。可能导致TDS错误的因素包括:数据库服务器正忙;数据库服务器自动关闭;正在断开网络连接。@Marc Gravell:Azure运行时调用
OnStop()
,作为更大角色“停止”序列的一部分。是的,我想;但缺点是:您看到的错误与锁/布尔无关;它之所以出错,是因为它正在被关闭。@Marc Gravell:那么你的猜测是问题出在程序之外。嗯,这是有道理的。你能从你的第一个评论中构思出一些简单的答案吗?
ThreadBClass.SetShouldStop();
const int count = 20;
for( int i = 0; i < count; i++ ) {
if( controlledThread.IsAlive ) {
break;
}
Thread.Sleep( 1000 );
}
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