2012-02-22 8 views
2

私はSMTPサーバーが遅く、多くのユーザーが欲求不満のために送信ボタンを押してしまうので、私はTPLを使ってメールをバックグラウンドで送信しています。過去に私は類似していたタスクを達成するためにSystem.Threadingと静的メソッドを使用していた - .NET3.5で、私のコードは次のように見えた:私はこの方法がなければならなかった覚えているのsendEmailの署名がpublic static void AddEmailToMailingListInBackground(object EmailString)だったとASP.NET 4.0でタスクパラレルライブラリを使用する場合の明確化

Thread t = new Thread(new ParameterizedThreadStart(SendEmail)); 
t.Start(txtEmail.Text); 

静的でなければならず、非同期メソッドにTextBox txtEmailの値を渡すか、ページライフサイクルが独立して続行されるため、コントロールの値へのアクセスが失われる危険があります。 System.Threading.Tasksを使用した場合

は今、私のコードは次のようになります。

Task.Factory.StartNew(() => SendEmail(), TaskCreationOptions.LongRunning); 

とのsendEmailの署名がprivate void SendEmail()と私は直接そのメソッド内txtEmailTextプロパティにアクセスします。

ここには2つの大きな違いがあります。まず、私の非同期メソッドはもはや静的である必要はありません。次に、スレッドの使用中にページのライフサイクルが完了した後、メソッドの中でPageのコントロール値にアクセスすることができます。これらの2つのポイントは、すべてのタスクが完了するかページのライフサイクルが完了するまでの間に、ページが生きていると信じるようになります。私は、非同期メソッドをデバッグして実行することでこれをテストしました。レスポンスはブラウザに送信されましたが、まだコントロールとその値にアクセスしてアクセスできます。 This MSDN articleはちょっと役立ちますが、まだTPLと非同期呼び出しを実行する前の.NET4の方法との違いを理解しているわけではありません。

誰も私の思考が正しかったのか、これはASP.NETでTPLを使用しているときに信頼できる動作であると言えますか?
さらに詳しく説明してもらえますか?

答えて

3

ではありません。 ASP.NETオブジェクトからASP.NETスレッドに安全にアクセスできます。 SendMailがページ/リクエストから必要とする詳細を抽出し、クロージャを介してそれらを渡すほうがずっと良いでしょう。

また、SendMailで発生する可能性のある例外を "観察"する必要があります。そうしないと、TPLは例外を発生させてWebアプリケーション全体をクラッシュさせます。これは、SendMail呼び出し自体の周りのtry/catchや、TaskContinuationOptions.OnlyOnFaultedオプション付きの別の継続の連鎖で行うことができます。継続的なアプローチでは、TPLがあなたが例外を「観察」したことを知るために、前回のExceptionプロパティにアクセスするだけで、おそらくログに記録する必要があります。だから、すべて一緒に、それは次のようになります。これを置くため

string userEmail = userEmailTextBox.Text; 
// whatever else SendMail might need from the page/request 

Task.Factory.StartNew(() => SendMail(userEmail)) 
      .ContinueWith(sendEmailAntecedent => 
          { 
           Trace.TraceError(sendEmailAntecedent.Exception.ToString()); 
          }, 
          TaskContinuationOptions.OnlyOnFaulted|TaskContinuationOptions.ExecuteSynchronously); 
+0

を感謝ドリュー、特に例外処理に関する警告に。明確化のためのいくつかの要求。 1)try/catchブロックでSendMailへの呼び出しをラップする際の動作に違いはありますか?OnlyOnFaultedオプションで継続を使用するかどうかをtry/catchブロックでSendMailの本文をラップしますか?私は少し読んで、メソッドの外にキャッチすると、AggregateExceptionを探すべきであることが分かりました[私は] – joelmdev

+1

@ jm2はい、そうです。 sendMailタスク自体にtry/catchを直接入れると、まっすぐな同期コードなので、例外はバニラの.NETコードのように伝播します。 ContinuationApproachを使用する場合、SendMailタスクの実行時に発生する例外はAggregateExceptionでラップされます。SendMailが完全に同期していることがわかっている場合、それを調べてさまざまなタイプに反応する必要がある場合は、簡単に/安全にAggregateException :: InnerExceptionプロパティから元の例外を取り出すことができます。 –

+0

コメントが壊れているために簡潔な部分2)値が直接変更される可能性があるため安全でないと言っていますか?コントロールとその値は、SynchronizationContextがページの状態を維持/復元しているために利用可能です。 – joelmdev

関連する問題