Hallo,
i get the exception below in a ASP.Net WebApp (using SQL-Server 2008), when a large amount of data is processed - and it seems this exception is thrown at a random location in the code.
What does this exception mean? Is it a timeout?
Thread was being aborted.
at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32 )
at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
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.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.Exec
Thanks!
If an application is idle for some time (meaning that no requests are coming in), or certain other conditions are met, ASP.NET will recycle the entire AppDomain . When that happens, any threads that you started from that AppDomain , including those from Application_Start , will be aborted.
When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException on . NET Framework. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block.
"Thread was being aborted" errors are, 99% of the time, caused by using Thread.Abort() from your code to end a process in any other circumstance than catastrophic failure. Thread.Abort is evil, because it injects an exception into the thread from outside its own executing code, and therefore it is extremely difficult, even impossible, to expect and gracefully handle it.
If you are running this code in another thread (good choice BTW; DB operations are a natural candidate for multithreading), DO NOT use Thread.Abort() to attempt to control the thread. You should instead construct the thread's code to be responsive to some outside change that you can trigger, that will cause it to gracefully end processing. Here's a simple example:
public class Foo
{
public void MainMethod()
{
bool cancel = false; //our external flag
//our worker thread, which is being given a callback method to poll at "safe" times.
var workerThread = new Thread(()=>AsyncMethod(()=>cancel));
//start the thread
workerThread.Start();
//do some other work that takes less time than the thread
Thread.Sleep(200)
//async thread is still going; cancel execution and wait for graceful exit.
cancel = true;
workerThread.Join();
}
public void AsyncMethod(Func<bool> wasCancelled)
{
//Do some repetitive task that takes longer than we're willing to wait
for(var i=1; i<2000; i++)
{
if(wasCancelled()) break; //generally a "safe" place to check
Thread.Sleep(50); //stand-in for some atomic operation that should not be interrupted.
}
if(wasCancelled())
Debug.WriteLine("Thread cancelled");
else
Debug.WriteLine("Thread completed");
}
}
This example does use a lambda with an "external closure"; if our method were to exit before the worker thread completes, the lambda would error out because the cancel variable was de-scoped and destroyed. Just keep these kinds of things in mind when adapting this model to your actual architecture; if you're starting the thread in one method and waiting for it to finish in another, while triggering the cancel in a third (a rather common circumstance actually), the flag must live somewhere where it will not be destroyed before the worker thread has ended execution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With