从SignalR集线器发送异步邮件 [英] Sending async mail from SignalR hub

查看:167
本文介绍了从SignalR集线器发送异步邮件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于SignalR中枢的调用,我需要发送电子邮件。我不希望发送同步执行,因为我不想绑定WebSocket连接,但是如果可能的话,我想通知呼叫者,如果有任何错误。我以为我可以在中心使用这样的东西(减号错误处理和我想要的所有其他事情):

  public class MyHub:Hub {
public async Task DoSomething(){
var client = new SmtpClient();
var message = new MailMessage(/ * setup message here * /);
等待client.SendMailAsync(message);
}
}

但很快就发现它不行; client.SendMailAsync调用抛出:


System.InvalidOperationException:此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的特定事件期间启动。


进一步的调查和阅读已经显示我认为SmtpClient.SendMailAsync是关于EAP方法的TAP包装,而且SignalR不允许。



我的问题是,是否有任何简单的方式异步发送电子邮件直接从集线器方式?



还是我唯一的选择将电子邮件发送代码放在别处? (例如,中心队列是服务总线消息,则独立服务可以处理这些消息并发送电子邮件[尽管我也有更多的工作来实现结果回到中心的客户端];或让中枢向发送电子邮件的Web服务发出HTTP请求)

解决方案

类似的问题 here 这里



SignalR团队是了解问题,但尚未修复。在这一点上,它似乎会进入SignalR v3。



同时,一个快速的黑客是这样的:

  public async任务DoSomething(){
using(new IgnoreSynchronizationContext())
{
var client = new SmtpClient();
var message = new MailMessage(/ * setup message here * /);
等待client.SendMailAsync(message);
}
}

public sealed class IgnoreSynchronizationContext:IDisposable
{
private readonly SynchronizationContext _original;
public IgnoreSynchronizationContext()
{
_original = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
}
public void Dispose()
{
SynchronizationContext.SetSynchronizationContext(_original);
}
}


I need to send an email as a result of a SignalR hub invocation. I don't want the send to execute synchronously, as I don't want to tie up WebSocket connections, but I would like the caller to be informed, if possible, if there were any errors. I thought I'd be able to use something like this in the hub (minus error handling and all other things that I want it to do):

public class MyHub : Hub {
    public async Task DoSomething() {
        var client = new SmtpClient();
        var message = new MailMessage(/* setup message here */);
        await client.SendMailAsync(message);
    }
}

But soon discovered that it won't work; the client.SendMailAsync call throws this:

System.InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle.

Further investigation and reading has shown me that SmtpClient.SendMailAsync is a TAP wrapper around EAP methods, and that SignalR does not allow that.

My question is, is there any simple way to asynchronously send the emails directly from a hub method?

Or is my only option to place the email sending code elsewhere? (e.g. have the hub queue a service-bus message, then a stand-alone service could handle those messages and send the emails [though I'd also have more work this way to implement notification of results back to the hub's clients]; or have the hub make an HTTP request to a webservice that does the email sending).

解决方案

Similar questions here and here.

The SignalR team is aware of the issue, but haven't fixed it yet. At this point it looks like it'll go into SignalR v3.

In the meantime, one quick hack would be this:

public async Task DoSomething() {
  using (new IgnoreSynchronizationContext())
  {
    var client = new SmtpClient();
    var message = new MailMessage(/* setup message here */);
    await client.SendMailAsync(message);
  }
}

public sealed class IgnoreSynchronizationContext : IDisposable
{
  private readonly SynchronizationContext _original;
  public IgnoreSynchronizationContext()
  {
    _original = SynchronizationContext.Current;
    SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
  }
  public void Dispose()
  {
    SynchronizationContext.SetSynchronizationContext(_original);
  }
}

这篇关于从SignalR集线器发送异步邮件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆