Eto*_* B. 35 c# email asynchronous visual-studio
我正在开发一个应用程序,用户点击/按下窗口中某个按钮的输入,应用程序执行一些检查并确定是否发送几封电子邮件,然后显示另一个带有消息的窗口.
我的问题是,发送2封电子邮件会显着减慢这个过程,并且在某些(约8)秒内,第一个窗口在进行发送时会看起来冻结.
有什么方法可以在后台发送这些电子邮件并立即显示下一个窗口吗?
请不要使用"使用X类"或"仅使用X方法"来限制您的答案,因为我还不太熟悉该语言,并且将非常感谢更多信息.
谢谢.
Bor*_*itz 68
从.NET 4.5开始,SmtpClient实现异步等待方法
SendMailAsync.因此,异步发送电子邮件如下:
public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage)
{
var message = new MailMessage();
message.To.Add(toEmailAddress);
message.Subject = emailSubject;
message.Body = emailMessage;
using (var smtpClient = new SmtpClient())
{
await smtpClient.SendMailAsync(message);
}
}
Run Code Online (Sandbox Code Playgroud)
Jam*_*mes 24
因为它是一个小工作单元,所以你应该使用ThreadPool.QueueUserWorkItem来处理它的线程方面.如果您使用SmtpClient类发送邮件,则可以处理SendCompleted事件以向用户提供反馈.
ThreadPool.QueueUserWorkItem(t =>
{
SmtpClient client = new SmtpClient("MyMailServer");
MailAddress from = new MailAddress("me@mydomain.com", "My Name", System.Text.Encoding.UTF8);
MailAddress to = new MailAddress("someone@theirdomain.com");
MailMessage message = new MailMessage(from, to);
message.Body = "The message I want to send.";
message.BodyEncoding = System.Text.Encoding.UTF8;
message.Subject = "The subject of the email";
message.SubjectEncoding = System.Text.Encoding.UTF8;
// Set the method that is called back when the send operation ends.
client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
// The userState can be any object that allows your callback
// method to identify this send operation.
// For this example, I am passing the message itself
client.SendAsync(message, message);
});
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the message we sent
MailMessage msg = (MailMessage)e.UserState;
if (e.Cancelled)
{
// prompt user with "send cancelled" message
}
if (e.Error != null)
{
// prompt user with error message
}
else
{
// prompt user with message sent!
// as we have the message object we can also display who the message
// was sent to etc
}
// finally dispose of the message
if (msg != null)
msg.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
通过每次创建一个新的SMTP客户端,您可以同时发送电子邮件.
Jus*_*ner 12
简单地在单独的线程上发送消息并不复杂:
using System.Net.Mail;
Smtp.SendAsync(message);
Run Code Online (Sandbox Code Playgroud)
或者,如果您想在单独的线程上构造整个消息,而不是仅仅异步发送它:
using System.Threading;
using System.Net.Mail;
var sendMailThread = new Thread(() => {
var message=new MailMessage();
message.From="from e-mail";
message.To="to e-mail";
message.Subject="Message Subject";
message.Body="Message Body";
SmtpMail.SmtpServer="SMTP Server Address";
SmtpMail.Send(message);
});
sendMailThread.Start();
Run Code Online (Sandbox Code Playgroud)
样品
using System;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;
using System.ComponentModel;
namespace Examples.SmptExamples.Async
{
public class SimpleAsynchronousExample
{
static bool mailSent = false;
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the unique identifier for this asynchronous operation.
String token = (string) e.UserState;
if (e.Cancelled)
{
Console.WriteLine("[{0}] Send canceled.", token);
}
if (e.Error != null)
{
Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
} else
{
Console.WriteLine("Message sent.");
}
mailSent = true;
}
public static void Main(string[] args)
{
// Command line argument must the the SMTP host.
SmtpClient client = new SmtpClient(args[0]);
// Specify the e-mail sender.
// Create a mailing address that includes a UTF8 character
// in the display name.
MailAddress from = new MailAddress("jane@contoso.com",
"Jane " + (char)0xD8+ " Clayton",
System.Text.Encoding.UTF8);
// Set destinations for the e-mail message.
MailAddress to = new MailAddress("ben@contoso.com");
// Specify the message content.
MailMessage message = new MailMessage(from, to);
message.Body = "This is a test e-mail message sent by an application. ";
// Include some non-ASCII characters in body and subject.
string someArrows = new string(new char[] {'\u2190', '\u2191', '\u2192', '\u2193'});
message.Body += Environment.NewLine + someArrows;
message.BodyEncoding = System.Text.Encoding.UTF8;
message.Subject = "test message 1" + someArrows;
message.SubjectEncoding = System.Text.Encoding.UTF8;
// Set the method that is called back when the send operation ends.
client.SendCompleted += new
SendCompletedEventHandler(SendCompletedCallback);
// The userState can be any object that allows your callback
// method to identify this send operation.
// For this example, the userToken is a string constant.
string userState = "test message1";
client.SendAsync(message, userState);
Console.WriteLine("Sending message... press c to cancel mail. Press any other key to exit.");
string answer = Console.ReadLine();
// If the user canceled the send, and mail hasn't been sent yet,
// then cancel the pending operation.
if (answer.StartsWith("c") && mailSent == false)
{
client.SendAsyncCancel();
}
// Clean up.
message.Dispose();
Console.WriteLine("Goodbye.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是使用.Net 4.5.2+的异步方法和异步方法:
BackgroundTaskRunner.FireAndForgetTaskAsync(async () =>
{
SmtpClient smtpClient = new SmtpClient(); // using configuration file settings
MailMessage message = new MailMessage(); // TODO: Initialize appropriately
await smtpClient.SendMailAsync(message);
});
Run Code Online (Sandbox Code Playgroud)
其中BackgroundTaskRunner是:
public static class BackgroundTaskRunner
{
public static void FireAndForgetTask(Action action)
{
HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => // .Net 4.5.2+ required
{
try
{
action();
}
catch (Exception e)
{
// TODO: handle exception
}
});
}
/// <summary>
/// Using async
/// </summary>
public static void FireAndForgetTaskAsync(Func<Task> action)
{
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => // .Net 4.5.2+ required
{
try
{
await action();
}
catch (Exception e)
{
// TODO: handle exception
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
就像Azure App Services上的魅力一样.
只是因为这有点模糊......我会简短的...
有很多方法可以在c#/ .net等中进行异步或并行工作.
做你想做的最快的方法是使用后台工作线程,这将避免锁定你的UI.
有后台工作线程的提示:你不能直接从它们更新UI(线程亲和力和编组只是你学会处理的东西......)
另一件需要考虑的事情......如果你使用标准的System.Net.Mail类型的东西来发送电子邮件......要小心你如何制作你的逻辑.如果你在某种方法中将它全部隔离并反复调用它,那么每次都可能必须拆除并重建与邮件服务器的连接,并且认证等所涉及的延迟仍然会不必要地减慢整个过程.在可能的情况下,通过单个打开的连接向邮件服务器发送多封电子邮件.
| 归档时间: |
|
| 查看次数: |
45668 次 |
| 最近记录: |