C# 在任务中进行异步/等待db调用?
我们有一个WCF服务,它以以下方式处理传入消息:C# 在任务中进行异步/等待db调用?,c#,wcf,asynchronous,task-parallel-library,async-await,C#,Wcf,Asynchronous,Task Parallel Library,Async Await,我们有一个WCF服务,它以以下方式处理传入消息: public bool ProcessMessage(string message) { var returnValue = GetReturnValue(); Task.Run(() => { //do some things with the message UpdateDatabase(); SendRepliesOverNetwork(); });
public bool ProcessMessage(string message)
{
var returnValue = GetReturnValue();
Task.Run(() => {
//do some things with the message
UpdateDatabase();
SendRepliesOverNetwork();
});
return returnValue;
}
为了处理尽可能多的消息,我们在这里添加了任务。我们希望尽快将returnValue返回给调用者,并让任务完成它的任务
我的问题:使用可等待的异步数据库调用和/或使用异步方法通过网络进行回复有什么好处吗?
我很谨慎,因为我认为这可能会造成太多的上下文切换。我们已经看到该应用程序使用了100多个线程。首先,我建议你退后一步,真正问问提前返回是否是个好主意。你所做的通常是危险的;在进行实际处理之前,您将向客户机返回“OK”。只有当您的客户知道“returnValue”并不意味着操作已完成,并且只有在收到“SendReplies”后才认为操作已完成时,这才是一个好主意 也就是说,是的,您应该看到尽可能使一切异步化的好处。如果您的所有任务都是非阻塞的,那么您可以更好地利用线程池(减少上下文切换)
我可以看到这种方法存在一些潜在的问题 首先,如果您在IIS中托管WCF服务,那么使用比请求寿命更长的后台线程是一个很大的禁忌。当请求完成时,IIS可以自由地拆除整个
AppDomain
,这将中止所有后台工作,并进行极端的预判断
其次,如果现有工作正在增加,WCF将限制请求。使用此模式,您可以快速处理请求,线程池的排队工作量可能会无限增加
您可以尝试使用WCF异步服务方法。这将释放正在等待IO的线程—您的数据库和网络访问—这可以提高吞吐量 这里有一篇关于这种方法的深入文章:
此外,MSDN中还有一个部分:这实际上取决于应用程序的上下文,是否希望在发送db更新后立即使UI响应,或者您是出于性能考虑才这样做的?我认为您在这里并没有等待任何东西:您正在线程池上排队工作,并立即返回调用方。@KyleC:为了性能。尽可能快地处理尽可能多的消息。@G.Stoynev:你是对的,只需将处理消息所需的所有工作排队即可。我想知道在db/网络访问上使用async/Wait是否会使线程在等待IO完成时可用于其他消息处理。returnValue基本上是一个应用程序级别的ack,用于告诉调用方我们收到了它的消息。因此,在调用生命周期之外进行处理是可以的。我将继续尝试异步db/网络调用。wcf服务是自托管的,所以我认为应该可以。我将研究wcf异步方法。由于该服务是自托管的,它现在成为您的问题,而不是IIS的问题。考虑一下应用关键服务器操作系统安全更新的计划;您需要知道wcf服务不忙的方式。
public bool ProcessMessage(string message)
{
var returnValue = GetReturnValue();
Task.Run(async () => {
//do some things with the message
await UpdateDatabaseAsync();
await SendRepliesOverNetworkAsync();
});
return returnValue;
}