错误:异步模块或处理程序已完成,而异步操作仍处于挂起状态

2023-11-29

我有一个控制器操作方法来保存用户详细信息,如下所示。

public async Task<ActionResult> SaveUser(ViewModel.VM_CreateUser user)
{
    var result = await _user.Save(userDetails);
    return Json(new { Success = String.IsNullOrEmpty(result) });
}

到目前为止,上述4行功能没有问题。

public async Task<ActionResult> SaveUser(ViewModel.VM_CreateUser user)
{
    var result = await _user.Save(userDetails);
    new MailController().CreateUser(user.userDetails); //<==This is problem line of code.
}

下面是我的邮件控制器。

public class MailController : MailerBase
{
    public void CreateUser(ViewModel.VM_User user)
    {
        To.Add(user.EmailAddress);
        From = System.Configuration.ConfigurationManager.AppSettings["emailSender"];
        Subject = "Hi";
        Email("CreateUser", user).DeliverAsync();
    }
}

在上面的代码中,我在执行电子邮件发送代码时遇到问题。我收到以下错误消息。

异步模块或处理程序在异步时完成 操作仍悬而未决

请提出纠正措施!


这是因为async方法跟踪它们的完成情况,甚至async void。他们通过注册来做到这一点SynchronizationContext启动时并在返回时标记操作完成。 ASP.NET 跟踪所有创建的操作,并要求它们在您的操作返回之前全部完成,否则它将向 HTTP 客户端返回错误。如果您需要运行“即发即忘”方法,则必须手动避免在 ASP.NET 上启动它SynchronizationContext。例如,await Task.Run(() => CallFireAndForget()) (await这样您就可以等待同步部分在线程池上运行。这有效是因为CallFireAndForget() is async void。触发一个返回 a 的方法Task作为一劳永逸的方式,你必须明确避免返回Task to Task.Run()像这样:await Task.Run(() => { CallFireAndForgetAsync(); })).

显示相同错误消息的另一种方法应该是将其写入异步操作中:

// BAD CODE, DEMONSTRATION ONLY!
AsyncOperationManager.CreateOperation();

如果您使用AsyncOperationAPI,你必须确保你调用AsyncOperation.OperationCompleted()在允许操作方法返回之前。

就您而言,如果邮件发送确实是一项即发即忘的任务,您可以在CreateUser将其签名更改为后async Task CreateUserAsync(ViewModel.VM_User user):

await Task.Run(() => Email("CreateUser", user).DeliverAsync());

并在你的行动中:

await new MailController().CreateUserAsync(user.userDetails);

理想情况下,你不会使用Task.Run()对于这样的事情。相反,您可以暂时替换当前的SynchronizationContext反而 (请注意:从不await在 - 的里面try{}- 相反,如果您需要,请存储Task在本地并恢复原始后等待它SynchronizationContext(使用原语可能更安全,例如SynchronizationContextSwitcher.NoContext() (source) 做正确的事)):

var originalSynchronizationContext = SynchronizationContext.Current;
try
{
    SynchronizationContext.SetSynchronizationContext(null);
    new MailController().CreateUser(user.userDetails);
}
finally
{
    SynchronizationContext.SetSynchronizationContext(originalSynchronizationContext);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

错误:异步模块或处理程序已完成,而异步操作仍处于挂起状态 的相关文章

随机推荐