我正在为ASP.NET Identity实现$customer = Mage::getSingleton("customer/session", array('name' => 'frontend'))->getCustomer();
。
我不喜欢EmailServer
与async...await
不兼容的方式,因此我的电子邮件方法是同步的。
那么如何从框架的using
方法中调用它呢?
SendAsync
在上面的代码中,public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
Email email = new Email();
return Task.FromResult<void>(email.Send(message));
}
}
给出了一个错误,指出Task.FromResult()
不能用作参数类型。但void
返回void!
如何走出这个泥潭?
答案 0 :(得分:9)
如果您没有结果,请不要尝试返回结果。只需返回一个简单的,完整的Task
:
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
new Email().Send(message);
return Task.CompletedTask;
}
}
如果你被困在4.6之前的土地上,那么你可以改用Task.FromResult<bool>(true)
。
所有这一切,我对您对“async...await
与using
”不兼容的评论感到困惑。根据我的经验,这很好。如果你的方法实际上是异步的,那会好得多。我认为通过专注于如何做到这一点会更好,而不是伪造async
方法的最佳/正确语法。
<强>附录:强>
我仍然不清楚您对使用using
的担忧。但是,根据您的评论,您似乎希望使用SmtpClient.SendAsync()
,但不确定如何在async
/ await
的上下文中应用该问题。
不幸的是,即使在async
/ await
之前,我们在.NET中有很多异步方法,并且这些方法使用与新等待方法的约定相同的命名。 (要清楚:这是不幸的命名,而不是异步方法存在:))。但是,在所有情况下,都可以将旧API调整为新的。
在某些情况下,它就像使用Task.FromAsync()
方法一样简单。这适用于支持旧Begin...
/ End...
模型的任何内容。但SmtpClient.SendAsync()
模型是一种基于事件的回调方法,需要稍微不同的方法。
注意:在编写下面的示例后,我注意到SmtpClient
类具有基于Task
的异步操作方法SendMailAsync()
。所以实际上,没有必要调整旧的SendAsync()
方法。但是这是一个有用的例子,用来说明在没有提供基于Task
的替代方案时如何进行这种调整。
简而言之,您可以在TaskCompletionSource
对象上使用SendCompleted
SmtpClient
事件。这是一个看起来像什么的概述:
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
// I'm not familiar with "IdentityMessage". Let's assume for the sake
// of this example that you can somehow adapt it to the "MailMessage"
// type required by the "SmtpClient" object. That's a whole other question.
// Here, "IdentityToMailMessage" is some hypothetical method you write
// to handle that. I have no idea what goes inside that. :)
using (MailMessage mailMessage = IdentityToMailMessage(message))
using (SmtpClient smtpClient = new SmtpClient())
{
TaskCompletionSource<bool> taskSource = new TaskCompletionSource<bool>();
// Configure "smtpClient" as needed, such as provided host information.
// Not shown here!
smtpClient.SendCompleted += (sender, e) => taskSource.SetResult(true);
smtpClient.SendAsync(mailMessage, null);
await taskSource.Task;
}
}
}
以上将启动异步操作,并使用SendCompleted
事件的处理程序(即文档引用的“回调”)来设置TaskCompletionSource<bool>
对象的结果(结果值为从来没有真正使用过,但是没有普通的Task
TaskCompletionSource
版本的await
......你必须拥有一些值。)
它使用taskSource.Task
,而不是直接返回SmtpClient
对象,因为这样可以在电子邮件操作实际完成时正确处理A
对象的处理。