2010-12-17 24 views
2

私は電子メールを送信する小さな電子メールワーカーを構築しようとしています。電子メールワーカーは、独自のスレッドで動作します。 global.asaxはスレッドを開始し、この例外をスローする前に1ラウンド実行します。私はそれをどこに投げるかを調べようとしていますが、毎回違うようです。レコードはテキストファイルに出力されるので、おそらく処分関数ですか? forループ メールワーカーに寝るASP.NET C#スレッドが異常終了しましたか?

メール 労働者の新しいラウンドを開始するためのループ

タイプの最初のチャンス 例外:

この例外がスローされますが 'System.Threading.ThreadAbortException' はがmscorlib.dll
例外に発生した 'System.Threading.ThreadAbortException'タイプ のはがmscorlib.dllで発生したが、これは、これがすべてを開始し、Global.asaxファイルである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; 
      } 
     } 
    } 
} 

するためのコードでユーザーコードで

を扱っ いませんでした。

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

答えて

1

作成しているスレッドがasp.netによってアボートされています。長時間実行しているスレッドを作成することは、asp.netの主要なno-noです。

私たちは誇りに思っていない解決策があります...保留中の電子メールを処理するタイマーを作成してください。

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メールで扱うので、タイマーティックが終了し、新しいものが上昇するには...

これは、当社の生産環境で作業します。..

+3

これは、24時間365日実行する必要があるものをASP.NETプロジェクトからWindowsサービスに移動する理由です。 –

0

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

+1

これは当てはまりません。アプリケーション内でスレッドを開始することはできますが、スレッドは特定の要求スレッドにバインドされていません。彼の例外は_このコードがスレッドに 'Abort()'を伝えるために発生しています。 – CodingGorilla

+0

@コーディングゴリラ - どこ?私が見ている唯一の打ち切りは、アプリケーションの最後です。リクエストスレッドにバインドされていない場合、なぜデバッグの最後の書き込みは中断する前に消えませんか?これまでAsp.Netのスレッドを他の用途に使用していましたが、アプリケーションレベルのコードにスレッド宣言を入れようとは決してしませんでした。 –

+0

私は最後の 'Debug.Write(e.Message)'は起動しないと思います。彼の例外を見ると、 '' System.Threading.ThreadAbortException '型の例外がmscorlib.dllで発生しましたが、ユーザコードでは処理されませんでした。これは最後のメッセージです。もしあなたが 'ThreadAbortException'でMSDNのドキュメントを読んでも、あなたは完全にそれをキャッチすることはできません。常に元通りです。 – CodingGorilla

0

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

EmailWorkerThread.Abort(); 

アプリケーションが終了すると、これは起こりません。

より良い実装は、無限ループをcancelableループに置き換えることです。

1

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

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

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

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

3

EmailWorkerをASP.NETからWindowsサービスに移動する必要があります。あなたはWCF経由であなたのWebページとサービスをやりとりすることができます。 ASP.NETは長時間実行されるタスクではありません。