在 C# 中使函数非阻塞/异步的简单方法?
Simple means of making a function non-blocking / async in C#?
我有一个按钮 - 当用户点击它时 - 发送一封电子邮件。我希望它立即 return 并在后台发送电子邮件,而无需在处理电子邮件时暂停 UI。我搜索了 async
/await
/etc,发现了很多不同的方法 - 我正在寻找一个简单的解决方案。我的电子邮件代码:
public void SendEmail(string toAddress, string subject, string body, string code = null) {
try {
var fromAddressObj = new MailAddress("noreply@me.com", "Name");
var toAddressObj = new MailAddress(toAddress, toAddress);
const string fromPassword = "Password";
var smtp = new SmtpClient {
Host = "smtp.office365.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddressObj.Address, fromPassword)
};
using (var message = new MailMessage(fromAddressObj, toAddressObj) {
Subject = subject,
IsBodyHtml = true
}) {
message.Body = body;
smtp.Send(message);
}
} catch (Exception e) {
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
}
}
我怎样才能修改这个以便不阻止来电者?
您可以 运行 在任务中使用您的方法而不是等待它:
private void button_Click(object sender, EventArgs e)
{
Task.Run( () => SendEMail(address, subject, body) );
}
SmtpClient
具有 SendMailAsync
,因此使用它而不是 Send
将在发送时解锁 UI 线程,但您仍然可以处理可能发生的任何异常:
private async void button_Click(object sender, EventArgs e)
{
await SendEmailAsync(address, subject, body)
}
public async Task SendEmailAsync(string toAddress, string subject, string body, string code = null)
{
try
{
var fromAddressObj = new MailAddress("noreply@me.com", "Name");
var toAddressObj = new MailAddress(toAddress, toAddress);
const string fromPassword = "Password";
var smtp = new SmtpClient {
Host = "smtp.office365.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddressObj.Address, fromPassword)
};
using (var message = new MailMessage(fromAddressObj, toAddressObj)
{
Subject = subject,
IsBodyHtml = true
})
{
message.Body = body;
await smtp.SendMailAsync(message);
}
}
catch (Exception e)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
}
}
如果 async
方法的同步部分(await
之前的部分)仍然设法阻塞 UI 线程,您可以将其卸载到 ThreadPool
线程:
private async void button_Click(object sender, EventArgs e)
{
await Task.Run(() => SendEmailAsync(address, subject, body))
}
备注:
- 不要在没有
await
的情况下启动 Task
除非你处于无法使用 await
的情况(UI 事件处理程序不是其中一种情况)
async void
仅适用于 UI 事件处理程序。不要在其他任何地方使用它。
我有一个按钮 - 当用户点击它时 - 发送一封电子邮件。我希望它立即 return 并在后台发送电子邮件,而无需在处理电子邮件时暂停 UI。我搜索了 async
/await
/etc,发现了很多不同的方法 - 我正在寻找一个简单的解决方案。我的电子邮件代码:
public void SendEmail(string toAddress, string subject, string body, string code = null) {
try {
var fromAddressObj = new MailAddress("noreply@me.com", "Name");
var toAddressObj = new MailAddress(toAddress, toAddress);
const string fromPassword = "Password";
var smtp = new SmtpClient {
Host = "smtp.office365.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddressObj.Address, fromPassword)
};
using (var message = new MailMessage(fromAddressObj, toAddressObj) {
Subject = subject,
IsBodyHtml = true
}) {
message.Body = body;
smtp.Send(message);
}
} catch (Exception e) {
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
}
}
我怎样才能修改这个以便不阻止来电者?
您可以 运行 在任务中使用您的方法而不是等待它:
private void button_Click(object sender, EventArgs e)
{
Task.Run( () => SendEMail(address, subject, body) );
}
SmtpClient
具有 SendMailAsync
,因此使用它而不是 Send
将在发送时解锁 UI 线程,但您仍然可以处理可能发生的任何异常:
private async void button_Click(object sender, EventArgs e)
{
await SendEmailAsync(address, subject, body)
}
public async Task SendEmailAsync(string toAddress, string subject, string body, string code = null)
{
try
{
var fromAddressObj = new MailAddress("noreply@me.com", "Name");
var toAddressObj = new MailAddress(toAddress, toAddress);
const string fromPassword = "Password";
var smtp = new SmtpClient {
Host = "smtp.office365.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddressObj.Address, fromPassword)
};
using (var message = new MailMessage(fromAddressObj, toAddressObj)
{
Subject = subject,
IsBodyHtml = true
})
{
message.Body = body;
await smtp.SendMailAsync(message);
}
}
catch (Exception e)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
}
}
如果 async
方法的同步部分(await
之前的部分)仍然设法阻塞 UI 线程,您可以将其卸载到 ThreadPool
线程:
private async void button_Click(object sender, EventArgs e)
{
await Task.Run(() => SendEmailAsync(address, subject, body))
}
备注:
- 不要在没有
await
的情况下启动Task
除非你处于无法使用await
的情况(UI 事件处理程序不是其中一种情况) async void
仅适用于 UI 事件处理程序。不要在其他任何地方使用它。