Что такое "Thread". 'на SNIReadSync (SNI_Conn *, SNI_Packet **, Int32)' означает?

Алло,

Я получаю исключение ниже в ASP.Net WebApp (используя SQL-Server 2008), когда обрабатывается большое количество данных - и похоже, что это исключение выбрасывается в случайном месте в коде.

Что означает это исключение? Это тайм-аут?

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

Спасибо!

Ответ 1

"Тема прерывается". Ошибки - 99% времени, вызванные использованием Thread.Abort() из вашего кода, чтобы закончить процесс в любых других обстоятельствах, кроме катастрофического сбоя. Thread.Abort - это зло, потому что он вводит исключение в поток из-за пределов своего собственного исполняемого кода, и поэтому чрезвычайно сложно и даже невозможно ожидать и грациозно обрабатывать его.

Если вы используете этот код в другом потоке (хороший выбор BTW, операции с БД являются естественным кандидатом для многопоточности), НЕ используйте Thread.Abort(), чтобы попытаться контролировать поток. Вместо этого вы должны создать код потока, который будет реагировать на некоторые внешние изменения, которые вы можете вызвать, что приведет к его изящному завершению обработки. Вот простой пример:

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");
    }
}

В этом примере используется лямбда с "внешним закрытием"; если наш метод должен был выйти до завершения рабочего потока, лямбда выйдет из строя, потому что отмененная переменная была удалена и уничтожена. Просто помните об этих вещах при адаптации этой модели к вашей реальной архитектуре; если вы начинаете поток в одном методе и ожидаете его завершения в другом, а при третьем отключении (довольно распространенное обстоятельство) флаг должен жить где-то там, где он не будет уничтожен до того, как рабочий поток будет завершенное выполнение.