2012-01-07 32 views
8

Khái niệm đơn giản tại đây. Điều này là dành cho một trang web đang được xây dựng bằng cách sử dụng MVC 3 và Entity Framework 4. Sau khi người dùng đăng ký trên trang web, một email được gửi đến địa chỉ email của họ. Lần đầu tiên tôi thực hiện điều này bằng cách sử dụng SmtpClient.Send() và nó hoạt động tốt. Sau đó, tôi đã có ý tưởng sáng để thử gửi email không đồng bộ. Tôi đang gặp sự cố với hai cách tiếp cận không đồng bộ mà tôi đã thử.Hai cách để gửi email qua SmtpClient không đồng bộ, các kết quả khác nhau

thi đầu tiên (từ bài chưa được trả lời này: 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); 
    } 
} 

này đã làm việc một nửa thời gian. Một nửa khác, tôi sẽ nhận được lỗi "Không thể truy cập một đối tượng được xử lý" trong CallBack.

thực hiện tiếp theo (từ một thành viên có uy tín vững chắc: 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); 

Với thi này, tôi không nhận được bất kỳ lỗi nào, nhưng có một sự chậm trễ đáng kể dài hơn (~ 5 giây) ở chế độ gỡ lỗi khi SmtpClient. SendAsync() thực thi, khiến tôi nghĩ rằng nó không được gửi một cách không đồng bộ.

Câu hỏi:

1) sai sót trong phương pháp đầu tiên gây ra lỗi "đối tượng được xử lý" là gì?

2) thực hiện lần hai có vấn đề khiến email không gửi không đồng bộ? Là sự chậm trễ 5 giây vô nghĩa? Cũng cần lưu ý rằng mặc dù trang web sẽ không cần hỗ trợ gửi một số lượng lớn email (chỉ đăng ký người dùng, bản tin chọn tham gia, v.v.), chúng tôi dự đoán một số lượng lớn người dùng trong tương lai, do đó quyết định gửi email của tôi không đồng bộ.

Cảm ơn.

Trả lời

7

Phương thức nắm tay của bạn sẽ không hoạt động bình thường do khối USING-block. Sau khi sử dụng khối kết thúc, đối tượng SmtpClient sẽ được xử lý. Vì vậy, bạn không thể truy cập vào nó trong trình xử lý sự kiện của bạn.

+0

Cảm ơn bạn đã trả lời. Bây giờ tôi thấy đối tượng được xử lý trước khi người xử lý có cơ hội bắn. Ngoài ra, tôi hiểu rằng cả SmtpClient phải được xử lý và EndInvoke phải được gọi. Cách tiếp cận # 2 có đạt được điều này không? –

5

lời khuyên: 1-dont sử dụng "sử dụng khối" cho MailMessage Objet, nó định đoạt đối tượng của bạn trước khi gửi email
2-xử lý đối tượng MailMessage trên SmtpClient.SendCompleted sự kiện:

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

3-bộ SendCompletedEventHandler cho đối tượng SmtpClient

smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); 

4-nhiều mã:

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 là phương pháp ưu tiên gửi email không đồng bộ vì phương thức này sử dụng các phương pháp SmtpClient được thiết kế đặc biệt cho mục đích này. Nó cũng đơn giản hơn để thực hiện và đã được chứng minh là hoạt động hàng ngàn lần.

Độ trễ 5 giây của bạn là lạ và cho thấy có sự cố cần giải quyết. Đoạn mã đầu tiên chỉ bao gồm vấn đề nhưng không loại bỏ nó.

SmtpClient.SendAsync thực sự sẽ chỉ gửi không đồng bộ nếu phương thức phân phối của bạn là khôngSpecifiedPickupDirectory hoặc PickupDirectoryFromIis. Trong những trường hợp đó, nó sẽ ghi tập tin tin nhắn vào thư mục pickup trước khi trở về. Kiểm tra phần cấu hình của tập tin cấu hình của bạn <smtp>. Tôi đoán bạn đang sử dụng một trong những phương pháp này và vấn đề là với thư mục pickup. Xóa các tệp cũ bạn có thể có ở đó và kiểm tra xem sự cố không phải là phần mềm chống vi-rút của bạn, nhiều khả năng tìm kiếm từng tệp mới cho vi-rút. Kiểm tra xem có thuộc tính nén hoặc mã hóa nào được đặt hay không. Có thể là cái gì khác nữa. Cách tốt nhất để kiểm tra xem thư mục có phải là nguồn gốc của các vấn đề hay không bằng cách sao chép thủ công một tệp email vào đó.

Các vấn đề liên quan