簡體   English   中英

ASP.NET C#線程異常中止?

[英]ASP.NET C# thread aborted exception?

我正在嘗試建立一個小的電子郵件工作者來發送我的電子郵件。 電子郵件工作程序在其自己的線程中運行。 global.asax啟動線程,然后運行一輪,然后拋出此異常。 我一直在嘗試找出將它扔到哪里,但是每次看起來都不同。 記錄被打印到文本文件中,以便工作,也許是處理功能?

這是引發的異常:

在電子郵件工作者循環中開始新的一輪
在電子郵件工作者循環中入睡
mscorlib.dll中發生類型'System.Threading.ThreadAbortException'的第一次機會異常
mscorlib.dll中發生類型'System.Threading.ThreadAbortException'的異常,但未在用戶代碼中處理

這是EmailWorker的代碼

public static class EmailWorker
{
    public static void Work()
    {
        TimeSpan sleepTime = new TimeSpan(0, 1, 0);

        for (; ; )
        {
            Debug.WriteLine("Starting a new round in the email worker for-loop");
            try
            {
                // Get the records
                CS_Code.UtopiaDataContext db = new CS_Code.UtopiaDataContext(); 
                List<CS_Code.Global_Email> emailsToSend = (from xx in db.Global_Emails select xx).ToList();


                // Write the records to a file (for now)
                TextWriter writer = new StreamWriter(@"test.txt", true); // For debugging
                foreach (var email in emailsToSend)
                    writer.WriteLine("To: " + email.Email_Address + ", Subject: " + email.Subject + ", uid:" + email.UserName.ToString());
                writer.Close();
                writer.Dispose();

                // Delete the used records from the database
                foreach (var email in emailsToSend)
                    db.Global_Emails.DeleteOnSubmit(email);
                db.SubmitChanges();
                db.Dispose();


                Debug.WriteLine("Going to sleep in the email worker for-loop");
                Thread.Sleep(sleepTime); // Sleep for 1 minute.
                Debug.WriteLine("Just woke up in the email worker for-loop");
            }
            catch (Exception e)
            {               
                Debug.WriteLine(e.Message);
                break;
            }
        }
    }
}

這是啟動所有內容的global.asax文件:

private static Thread EmailWorkerThread { get; set; }

void Application_Start(object sender, EventArgs e)
{
    // Email worker thread
    if ((EmailWorkerThread == null) || (!EmailWorkerThread.IsAlive))
    {
        ThreadStart ts = new ThreadStart(EmailWorker.Work);
        EmailWorkerThread = new Thread(ts);
        EmailWorkerThread.Start();
    }
}

void Application_End(object sender, EventArgs e)
{
    // Email worker thread
    if ((EmailWorkerThread != null) || (EmailWorkerThread.IsAlive))
        EmailWorkerThread.Abort();
    EmailWorkerThread = null;
}

您需要將EmailWorker移出ASP.NET並移到Windows服務中。 您可以通過WCF在網頁和服務之間進行通信。 ASP.NET不適用於長時間運行的任務。

當您的應用程序關閉並調用EmailWorkerThread.Abort()時,將發生ThreadAbortException 這是預期的行為,它發生在隨機的位置,因為當Application_End在線程上調用Abort()時,代碼可能位於不同的“位置”。

根據MSDNThreadAbortException是一個特殊的異常,即使在您的代碼處理之后,該異常也總是被拋出。 目的是讓您知道線程正在關閉,以便您有機會進行清理。

您的應用程序可能已關閉,因為IIS在設置了一定的空閑時間或某些其他限制后關閉了工作進程。 同樣,這是可以預期的,ASP.NET應用程序往往具有“有限的生存期”,因此,像這樣長時間運行的線程並不是一個好主意。

我不確定您的確切問題是什么,但希望我能回答。

您正在創建的線程被asp.net中止。 在asp.net中,創建長時間運行的線程是一個主要的禁忌。

A我們有一個可行的解決方法,我們不為此感到驕傲...創建一個計時器來處理未決的電子郵件。

static Timer processTimer; // declare static at service level

// At the static constructor:
processTimer = new Timer(new TimerCallback(TimerTick), 60000, 10000, defaultInterval); //wait a minute before begin (dueTime = 60000)

要特別小心,在Timer_Tick事件中,最多處理N封電子郵件,因此計時器滴答結束,並且新的滴答出現……

這正在我們的生產環境中進行...

子線程僅在父線程處於活動狀態時才能存在。 即使您在似乎是應用程序級別的位置上定義了一個線程,我也無法想象該線程實際上可以在HttpRequest線程之外生存。 對我來說,這意味着您的請求線程終止時,您的子級EmailWorkerThread終止。 由於線程處於休眠狀態,因此下一行嘗試執行,但由於HttpRequest線程已經運行,因此無法執行。

ThreadAbortException顧名思義,當線程正在工作並且中止時拋出該異常。 這發生在這個地方:

 EmailWorkerThread.Abort();

無法捕獲它,並且在應用程序結束時會發生。

更好的實現是將無限循環替換為可取消循環。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM