C# 在ASP.net中努力实现异步部署

C# 在ASP.net中努力实现异步部署,c#,asp.net,async-await,deadlock,C#,Asp.net,Async Await,Deadlock,代码在我的开发环境中运行良好,但在可伸缩体系结构的部署中,它似乎处于死锁状态 这里的目标是获取一个要发送到SendGrid的API请求队列,对它们进行批处理,并一次处理一个批处理 来自ASHX处理程序的第一次呼叫 public void ProcessRequest(HttpContext context) { var result = Code.Helpers.Email.Sendgrid.Queue.Process().Result; if (result.Success)

代码在我的开发环境中运行良好,但在可伸缩体系结构的部署中,它似乎处于死锁状态

这里的目标是获取一个要发送到SendGrid的API请求队列,对它们进行批处理,并一次处理一个批处理

来自ASHX处理程序的第一次呼叫

public void ProcessRequest(HttpContext context)
{
    var result = Code.Helpers.Email.Sendgrid.Queue.Process().Result;
    if (result.Success)
    {
Queue.Process()

公共静态异步任务进程()
{
var queueItems=GetQueueItemsToProcess();
var batches=BatchQueueItems(queueItems);
foreach(批量var)
{
var r=wait batch.SendToSendGrid();
if(r.停止批次)
{
打破
}
}
返回新的GenericMethodResult(true);
}
SendToSendGrid()

公共异步任务SendToSendGrid()
{
var r=new SendGridAPIMethodResponse();
var json=API.Functions.CreateJSONData(这个);
var sg=新的SendGridClient(Settings.Email.SendgridAPIKey);
动态响应;
if(Action==Action.UpdateRecipient)
{
response=wait sg.RequestAsync(SendGridClient.Method.PATCH,urlPath:“contactdb/recipients”,requestBody:json);
}
字符串jsonResponse=response.Body.ReadAsStringAsync().Result;
//进程响应。。。
返回r;
}
我已经尽可能地剥离了代码


有人能告诉我为什么此代码在生产中超时吗?

此对
的阻塞调用。
SendToSendGrid()
中的结果
在混合异步和阻塞调用时导致死锁

string jsonResponse = response.Body.ReadAsStringAsync().Result;
始终使用异步

var jsonResponse = await response.Body.ReadAsStringAsync();
并尽量避免在异步方法中混合阻塞调用

您还应该考虑使用
httptasksynchHandler
使处理程序异步

public class MyHandler : HttpTaskAsyncHandler {
    public override async Task ProcessRequestAsync(HttpContext context) {
        var result = await Code.Helpers.Email.Sendgrid.Queue.Process();
        if (result.Success) {
            //..other code
        }
    }
}

那太棒了,帮了我很多忙。我可以看到
SendToSendGrid()
正在完成执行,但似乎在某个地方仍然存在死锁。链中是否还有其他原因可能导致这种情况?不确定它是否重要,但函数需要访问当前的httpcontext,其中是否包括ASHX处理程序本身?我很困惑为什么会阻塞,我只想让ASHX处理程序运行这个函数。如果我可以避免异步,我会这样做,但sendgrid api似乎没有任何同步函数。有没有更简单的方法?我所要做的只是向SendGrid的API发送一个请求,并处理响应。它在处理程序中,每60秒作为作业调用一次。谢谢,我更新了答案,提到它来自ASHXCheck,为什么像
Wait
Result
这样的调用会导致挂起一个异步调用,这是一个有据可查的行为。由于ASP.Net入口点可以是异步的,所以等待是最好的选择,但对于控制台应用程序来说,它是不同的,因为主入口点不是异步的。您似乎直接从处理程序发送电子邮件。虽然这会起作用,但最好通过电子邮件发送。如果电子邮件服务器(在这种情况下是web服务器)速度慢怎么办?或者如果它暂时关闭了呢?可能更好的做法是将电子邮件排队,并能够重试发送等@Mason it不发送电子邮件,而是将联系人数据与他们的联系人API同步。它有合理的速率限制,因此每分钟最多只能运行约50次。它是用分布式锁锁定的,因此如果再次调用它,它将在忙时返回,而不做任何操作。如果失败,它不会从队列中删除项目,并将稍后重试。它被设置为Azure计划任务,每分钟调用此URL。由于缓存的原因,很难将其与网站本身分离。这仍然是一个外部服务调用。由你决定。我只是不希望我的应用程序的用户仅仅因为其他第三方服务的速度慢/不可用而有一个缓慢/糟糕的体验。@Mason它会如何降低用户的体验?这是一个相当简单的队列处理器。队列引入的延迟对于最终用户是不可见的。啊,我现在看到您已经更新了您的注释,它是由计划任务调用的,而不是通过AJAX作为用户交互的结果。好吧,那么你是对的,在这种情况下它不会让用户慢下来。但这就引出了一个问题,为什么要通过ASP.NET站点中的处理程序公开该功能?为什么不让计划任务直接运行代码,或者使用更适合Azure中作业的东西?
var jsonResponse = await response.Body.ReadAsStringAsync();
public class MyHandler : HttpTaskAsyncHandler {
    public override async Task ProcessRequestAsync(HttpContext context) {
        var result = await Code.Helpers.Email.Sendgrid.Queue.Process();
        if (result.Success) {
            //..other code
        }
    }
}