2012-01-07 9 views
8

ここでは単純な概念です。これは、MVC 3およびEntity Framework 4を使用して構築されたサイト向けです。ユーザーがサイトに登録すると、電子メールがその電子メールアドレスに送信されます。私は最初にSmtpClient.Send()を使用してこれを実装し、正常に動作しました。それから私は電子メールを非同期的に送信しようとする明るいアイディアを得ました。私が試みた2つの非同期アプローチに関する問題が発生しています。SmtpClient経由で電子メールを非同期に送信する2つの方法、異なる結果

(この未解答のポストから:https://stackoverflow.com/questions/7558582/how-to-dispose-using-smtpclient-send-and-asynccallback):最初の実装

public bool Emailer(){ 
    . 
    . 
    . 
    using (var smtpClient = new SmtpClient()) 
    { 
     smtpClient.EnableSsl = true; 
     smtpClient.Host = "smtp.gmail.com"; 
     smtpClient.Port = 587; 
     smtpClient.UseDefaultCredentials = false; 
     smtpClient.Credentials = new NetworkCredential("[email protected]", "mypassword"); 

     var sd = new SendEmailDelegate(smtpClient.Send); 
     var cb = new AsyncCallback(SendEmailResponse); 
     sd.BeginInvoke(message, cb, sd); 

     return true; 
    } 
} 

private delegate void SendEmailDelegate(System.Net.Mail.MailMessage m); 

private static void SendEmailResponse(IAsyncResult ar) 
{ 
    try 
    { 
     SendEmailDelegate sd = (SendEmailDelegate)(ar.AsyncState); 
     sd.EndInvoke(ar); // "cannot access a disposed object" errors here 
    } 
    catch (Exception e) 
    { 
     _logger.WarnException("Error on EndInvoke.", e); 
    } 
} 

これは半分の時間を働いていました。残りの半分は、コールバックで「廃棄オブジェクトにアクセスできません」というエラーが表示されます。 (固体評判を持つメンバーから:What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0):

次実装

var smtpClient = new SmtpClient(); 
smtpClient.EnableSsl = true; 
smtpClient.Host = "smtp.gmail.com"; 
smtpClient.Port = 587; 
smtpClient.UseDefaultCredentials = false; 
smtpClient.Credentials = new NetworkCredential("[email protected]", "mypassword"); 

smtpClient.SendCompleted += (s, e) => 
    { 
     smtpClient.Dispose(); 
     message.Dispose(); 
    }; 
smtpClient.SendAsync(message, null); 
私はすべてのエラーを取得いけない、この実装では

が、smtpClientデバッグモードで著しく長い遅延(約5秒)があります。 SendAsync()が実行され、非同期に送信されていないと思うようになりました。

質問:

1)「破棄されたオブジェクト」のエラーを引き起こしている第一の方法で間違って何ですか?

2)2番目の実装でメールが非同期に送信されないという問題がありますか? 5秒の遅延は意味がありませんか?

サイトで多数の電子メール(ユーザー登録、オプトインニュースレターなど)の送信をサポートする必要はありませんが、将来的には多数のユーザーが参加する予定ですが、したがって、電子メールを非同期で送信することにしました。

ありがとうございました。

答えて

7

USINGブロックのため、あなたのfistメソッドは正しく動作しません。使用ブロックが終了すると、SmtpClientオブジェクトが破棄されます。したがって、イベントハンドラ内でアクセスすることはできません。

+0

返信いただきありがとうございます。ハンドラが発射する前にオブジェクトが処分されたことがわかりました。また、私は、SmtpClientを削除し、EndInvokeを呼び出さなければならないことを理解しています。 #2のアプローチはこれを達成していますか? –

5

ヒント:メールを送信する前に 1-いけないの使用はMailMessageのオブジェは、 "ブロックを使用するには"、それはあなたのオブジェクトを配置
2-処分SmtpClient.SendCompletedイベントにはMailMessageオブジェクトを:

smtpClient.SendCompleted += (s, e) => 
    { 
     message.Dispose(); 
    }; 

3セットsmtpClientオブジェクトのSendCompletedEventHandler

smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); 

4-複数コード:

private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) 
    { 
     // Get the unique identifier for this asynchronous operation. 
     String token = (string)e.UserState; 

     if (e.Cancelled) 
     { 
      //write your code here 
     } 
     if (e.Error != null) 
     { 
      //write your code here 
     } 
     else //mail sent 
     { 
      //write your code here 
     } 

     mailSent = true; 
    } 
1

SmtpClient.SendAsyncは、この目的のために特別に設計された方法SmtpClientを使用しているため、非同期電子メール送信の好ましい方法です。また、実装が簡単で、何千もの作業が実証されています。

あなたの5秒の遅延は奇妙で、アドレッシングが必要な問題があることを示唆しています。コードの最初の部分は問題を取り上げているだけですが、それを排除するものではありません。あなたの配信方法は、SpecifiedPickupDirectoryPickupDirectoryFromIisない場合

SmtpClient.SendAsyncは、実際には非同期で送信されます。その場合、メッセージファイルはピックアップフォルダに書き込まれてから返されます。設定ファイルの<smtp>セクションを確認してください。私の推測では、これらの方法のうちの1つを使用していますが、問題はピックアップフォルダにあります。古いファイルを削除して、新しいファイルごとにウイルスの可能性が高いウイルス対策ソフトウェアが問題でないかどうかを確認してください。暗号化または圧縮属性が設定されているかどうかを確認します。他の何かにすることもできます。フォルダが問題の原因であるかどうかをテストする最良の方法は、電子メールファイルを手作業で対処することです。

関連する問題