2

メールを送信する小さなメールワーカーを構築しようとしています。電子メール ワーカーは独自のスレッドで動作します。global.asax はスレッドを開始し、この例外をスローする前に 1 ラウンド実行します。投げる場所を調べてみたのですが、毎回違うようです。レコードはテキスト ファイルに出力されるので、おそらく破棄機能でしょうか?

これはスローされる例外です:

電子メール ワーカーの for ループで新しいラウンドを開始する 電子メール ワーカーの for ループ
でスリープ状態になる
mscorlib.dll で「System.Threading.ThreadAbortException」タイプの最初の例外が発生しまし
た 「System.Threading.ThreadAbortException」タイプの例外が発生しましたmscorlib.dll で発生しましたが、ユーザー コードでは処理されませんでした

これは 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;
}
4

5 に答える 5

3

EmailWorker を ASP.NET から Windows サービスに移動する必要があります。Web ページとサービスの間で WCF を介して通信できます。ASP.NET は長時間実行されるタスク向けではありません。

于 2011-03-15T22:06:42.783 に答える
1

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

これは私たちの本番環境で動作しています...

于 2010-12-17T15:05:07.277 に答える
1

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

MSDNによると、これはThreadAbortExceptionコードによって処理された後でも常に再スローされる特別な例外です。これは、クリーンアップの機会を提供するために、スレッドがシャットダウンしていることを知らせることを目的としています。

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

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

于 2010-12-17T14:59:32.703 に答える
0

ThreadAbortException名前が示すように、スレッドが動作しているときにスローされ、中止されます。これは次の場所で発生します。

 EmailWorkerThread.Abort();

キャッチできず、アプリケーションが終了したときに発生します。

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

于 2010-12-17T14:58:15.290 に答える
0

子スレッドは、親スレッドが生きている限り存続できます。アプリケーション レベルのように見えるスレッドが定義されていても、このスレッドが HttpRequest スレッドの外で実際に生き残っているとは思えません。私にとってこれは、リクエスト スレッドが終了した瞬間に、子の EmailWorkerThread が終了することを意味します。スレッドがスリープ状態にあるため、次の行を実行しようとしますが、HttpRequest スレッドが既にそのコースを実行しているため実行できません。

于 2010-12-17T14:54:40.323 に答える