2012-01-07 2 views
8

간단한 개념은 여기에 있습니다. 이것은 MVC 3 및 ​​Entity Framework 4를 사용하여 빌드되는 사이트 용입니다. 사용자가 사이트에 등록하면 전자 메일이 전자 메일 주소로 전송됩니다. SmtpClient.Send()를 사용하여이 기능을 처음으로 구현했으며 정상적으로 작동했습니다. 그런 다음 전자 메일을 비동기 적으로 보내려는 생각이 듭니다. 내가 시도한 두 가지 비동기 방식의 문제가 발생합니다. (이 답이 포스트에서 : https://stackoverflow.com/questions/7558582/how-to-dispose-using-smtpclient-send-and-asynccallback) :비동기식으로 SmtpClient를 통해 이메일을 보내는 두 가지 방법, 다른 결과

첫 번째 구현은

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("my[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) 두 번째 구현에 이메일이 비동기 적으로 전송되지 않는 문제가 있습니까? 5 초 지연은 의미가 없습니까?

사이트에서 많은 수의 이메일 (사용자 등록, 가입 뉴스 레터 등)을 보낼 필요가 없지만 앞으로 많은 사용자를 예상 할 수는 있지만, 따라서 이메일을 비동기 적으로 보내는 결정.

감사합니다.

답변

7

USING 블록으로 인해 주먹 방법이 제대로 작동하지 않습니다. using 블록이 끝나면 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 초 지연이 이상하며 주소 지정이 필요한 문제가 있음을 나타냅니다. 첫 번째 코드는 문제를 해결하는 것일뿐 문제를 해결하지는 못합니다.전달 방법은 하지SpecifiedPickupDirectory 또는 PickupDirectoryFromIis 경우

SmtpClient.SendAsync 실제로에만 비동기 전송합니다. 이 경우 메시지 파일을 다시 가져 오기 전에 pickup 폴더에 씁니다. 구성 파일의 <smtp> 섹션을 확인하십시오. 내 생각 엔이 방법 중 하나를 사용하고 있으며 픽업 폴더에 문제가있는 것입니다. 오래된 파일을 삭제하고 문제가 새 파일마다 바이러스를 가장 많이 검색하는 바이러스 백신 소프트웨어가 아닌지 확인하십시오. 암호화 또는 압축 속성이 설정되어 있는지 확인하십시오. 다른 것도있을 수 있습니다. 폴더가 문제의 원인인지 테스트하는 가장 좋은 방법은 전자 메일 파일을 수동으로 복사하여 문제를 해결하는 것입니다.

관련 문제