首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从SignalR集线器发送异步邮件

从SignalR集线器发送异步邮件
EN

Stack Overflow用户
提问于 2014-06-24 01:37:49
回答 2查看 2.5K关注 0票数 5

由于SignalR集线器调用,我需要发送一封电子邮件。我不希望发送同步执行,因为我不想绑定WebSocket连接,但如果可能的话,我希望调用方得到通知,如果有错误的话。我想我可以在集线器中使用这样的东西(减去错误处理和我希望它做的所有其他事情):

代码语言:javascript
复制
public class MyHub : Hub {
    public async Task DoSomething() {
        var client = new SmtpClient();
        var message = new MailMessage(/* setup message here */);
        await client.SendMailAsync(message);
    }
}

但很快就发现它无法工作;client.SendMailAsync调用抛出了以下内容:

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

进一步的研究和阅读已经告诉我,SmtpClient.SendMailAsync是EAP方法的一个TAP包装器,而SignalR不允许这样做。

我的问题是,有什么简单的方法可以直接从集线器方法异步发送电子邮件吗?

还是我唯一的选择是把电子邮件发送代码放在其他地方?(例如,让集线器排队一条服务总线消息,然后独立的服务可以处理这些消息并发送电子邮件,尽管我还需要做更多的工作来实现结果通知给集线器的客户端;或者让中心向完成电子邮件发送的webservice发出HTTP请求)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-24 12:13:18

类似的问题这里这里

SignalR团队是意识到这个问题,但还没有修复它。在这一点上,它看起来将进入SignalR v3。

在此期间,一个快速的黑客将是:

代码语言:javascript
复制
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);
  }
}
票数 7
EN

Stack Overflow用户

发布于 2014-06-24 12:12:10

我的理解是,最初的EAP风格的SmtpClient.SendAsync (被SendMailAsync包装为TAP)调用SynchronizationContext.Current.OperationStarted/OperationCompleted。据称,这就是让SignalR主机不开心的原因。

作为一种解决办法,以这种方式尝试(未经测试)。如果对你有用的话请告诉我们。

代码语言:javascript
复制
public class MyHub : Hub {
    public async Task DoSomething() {
        var client = new SmtpClient();
        var message = new MailMessage(/* setup message here */);
        await TaskExt.WithNoContext(() => client.SendMailAsync(message));
    }
}

public static class TaskExt
{
    static Task WithNoContext(Func<Task> func)
    {
        Task task;
        var sc = SynchronizationContext.Current;
        try
        {
            SynchronizationContext.SetSynchronizationContext(null);
            task = func();
        }
        finally
        {
            SynchronizationContext.SetSynchronizationContext(sc);
        }
        return task;
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24377081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档