質問

私は自分のメールを送信する小さな電子メールワーカーを構築しようとしています。電子メールワーカーは独自のスレッドで動作します。 Global.Asaxはスレッドを開始し、この例外をスローする前に1ラウンドで実行されます。私はそれがどこに投げられるかを見つけようとしてきましたが、それは毎回異なっているようです。レコードはテキストファイルに印刷されているため、機能するのかもしれません。

これはスローされた例外です。

ループのために電子メールワーカーで新しいラウンドを開始します
ループのためにメールワーカーで眠りにつく
タイプ「System.threading.threadabortexception」の最初のチャンスの例外がmscorlib.dllで発生しました
タイプ「System.Threading.ThreadAbortException」の例外はmscorlib.dllで発生しましたが、ユーザーコードでは処理されませんでした

これは、電子メールワーカーのコードです

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;
}
役に立ちましたか?

解決

作成しているスレッドは、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メールで処理するため、タイマーのティックが終了し、新しいものが上昇します...

これは私たちの生産環境に取り組んでいます...

他のヒント

メールワーカーをASP.NETからWindowsサービスに移動する必要があります。 WCFを介してWebページとサービス間で通信できます。 ASP.NETは、長期にわたるタスクを対象としたものではありません。

ThreadAbortException アプリケーションがシャットダウンして電話したときに発生します EmailWorkerThread.Abort(). 。これは予想される動作であり、コードが異なる「スポット」にあるときにランダムな場所で発生します。 Application_End 電話 Abort() スレッド上。

に従って MSDN, 、 ThreadAbortException コードで処理された後でも、常にret延している特別な例外です。それは、スレッドがシャットダウンしてきれいになることを知らせることを目的としています。

IISは、一定のアイドル時間、または他の課された制限の後に労働者プロセスをシャットダウンしているため、アプリケーションがシャットダウンされている可能性があります。繰り返しますが、これは予想されることです。ASP.NETアプリケーションは「寿命が限られている」傾向があるため、このような長いランニングスレッドは本当に良い考えではありません。

あなたの正確な質問が何であるかはわかりませんが、うまくいけば答えました。

子スレッドは、親スレッドが生きている限り生きることができます。アプリケーションレベルのように見えるもので定義されたスレッドがありますが、このスレッドが実際にHTTPRequestスレッドの外で生き残るとは想像できません。私にとって、これはあなたの要求スレッドが終了した瞬間に、あなたの子供の電子メールworkerthreadが終了することを意味します。スレッドは睡眠中であるため、次の行は実行を試みますが、HTTPRequestスレッドがすでにコースを実行しているためにはできません。

ThreadAbortException 名前が示すように、スレッドが機能しているときにスローされ、中止されます。これはこの場所で起こります:

 EmailWorkerThread.Abort();

捕まえることはできず、アプリケーションが終了すると発生します。

より良い実装は、無限のループをに置き換えることです キャンセル可能 ループ。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top