C# 使用多个长时间运行的操作优化ASMX web服务

C# 使用多个长时间运行的操作优化ASMX web服务,c#,performance,web-services,multithreading,asmx,C#,Performance,Web Services,Multithreading,Asmx,我正在使用具有DoLookup()函数的C编写一个ASP.NET web服务。对于DoLookup()函数的每次调用,我需要我的代码来执行两个单独的查询:一个到远程站点的另一个web服务,另一个到本地数据库。在编译结果并将其作为对DoLookup方法的响应返回之前,这两个查询都必须完成。我要处理的问题是,我希望尽可能提高效率,无论是在响应时间还是在web服务器上的资源使用方面。我们预计每小时会有数千个查询。以下是我到目前为止的大致C#式概述: public class SomeService :

我正在使用具有DoLookup()函数的C编写一个ASP.NET web服务。对于DoLookup()函数的每次调用,我需要我的代码来执行两个单独的查询:一个到远程站点的另一个web服务,另一个到本地数据库。在编译结果并将其作为对DoLookup方法的响应返回之前,这两个查询都必须完成。我要处理的问题是,我希望尽可能提高效率,无论是在响应时间还是在web服务器上的资源使用方面。我们预计每小时会有数千个查询。以下是我到目前为止的大致C#式概述:

public class SomeService : System.Web.Services.WebService
{
    public SomeResponse DoLookup()
    {
        // Do the lookup at the remote web service and get the response 
        WebResponse wr = RemoteProvider.DoRemoteLookup();   

        // Do the lookup at the local database and get the response
        DBResponse dbr = DoDatabaseLookup();

        SomeResponse resp = new SomeResponse( wr, dbr);

        return resp;
    }
}
上面的代码按顺序执行所有操作,效果很好,但现在我想让它更具可伸缩性。我知道我可以异步调用DoRemoteLookup()函数(RemoteProvider有BeginRemoteLookup/EndRemoteLookup方法),并且我还可以使用BeginExecutenQuery/EndExecutenQuery方法异步执行数据库查找

我的问题(最后)是:如何在不同的线程上同时启动远程web服务查找和数据库查找,并确保它们在返回响应之前都已完成

我希望在单独的线程上执行这两个请求的原因是它们都可能有很长的响应时间(1或2秒),并且我希望在web服务器等待响应时释放web服务器的资源来处理其他请求。另一个注意事项是,我目前确实异步运行了远程web服务查找,我只是不想让上面的示例太混乱。我要做的是同时启动远程服务查找和数据库查找,并确定它们何时完成


谢谢您的建议。

假设您可以为web请求和数据库查找提供回调函数,那么这些方法可能会奏效

bool webLookupDone = false;
bool databaseLookupDone = false;

private void FinishedDBLookupCallBack()
{
    databaseLookupDone = true;
    if(webLookupDone)
    {
        FinishMethod();
    }
}

private void FinishedWebLookupCallBack()
{
    webLookupDone = true;
    if(databaseLookupDone)
    {
        FinishMethod();
    }
}

您可以使用一对
自动resetEvents
,每个线程一个。在线程执行结束时,调用
AutoResetEvents.Set()
来触发事件

生成线程后,您可以将
WaitAll()
与两个自动resetEvent一起使用。这将导致线程阻塞,直到设置了这两个事件

这种方法需要注意的是,必须确保Set()被保证调用,否则将永远阻塞。另外,请确保使用线程执行正确的异常处理,否则,当非故意的异常导致web应用程序重新启动时,会无意中导致更多性能问题

请参见,和

但请注意这些条款的第一段:

此主题特定于传统技术。现在应使用创建XML Web服务和XML Web服务客户端。



顺便说一句,按照这些文章所说的方式做事很重要,因为它可以在长时间运行的任务运行时释放ASP.NET工作线程。否则,您可能会阻止工作线程,阻止它为进一步的请求提供服务,并影响可伸缩性。

我想我没有足够的代表进行投票或发表评论。这是对约翰·桑德斯答案和艾伦对它的评论

如果您关心可伸缩性和资源消耗,那么您肯定希望使用John的答案

这里有两个考虑因素:加快单个请求的速度,以及使系统高效地处理多个并发请求。前者艾伦和约翰的答案都是通过并行执行外部调用来实现的

后者,听起来像是您主要关心的,是通过不在任何地方阻塞线程来实现的,即John的答案

不要产生你自己的线程。线程是昂贵的,如果您使用.net framework提供的异步方法,IO线程池中已经有很多线程可以为您处理外部调用


您的服务的webmethod也需要是异步的。否则,工作线程将被阻塞,直到外部调用完成(即使它们并行运行,也需要1-2秒)。每个CPU只有12个线程来处理传入请求(如果machine.config是根据设置的),也就是说,最多可以处理12个并发请求(乘以CPU的#)。另一方面,如果您的web方法是异步的,则Begin将立即返回,并且返回到工作线程池的线程准备好处理另一个传入请求,而IO完成端口正在等待您的外部调用,IO线程池中的线程将处理这些调用,一旦他们回来。

您是否在web服务中使用线程?在.net平台上,任何东西在web上的线程都是非常有限的。@Charles Conway:你读过下面的答案吗?你说的“有限”是什么意思?在这种情况下,调用需要同时执行。WebService调用本身不是异步的——它必须在将结果返回给调用方之前完成查找。我不明白为什么这些技术不能工作。如果你认为你的两个异步方法是一个单一的、复合的异步方法,那么你应该能够感谢约翰的链接。我确实计划让DoLookup调用异步,一旦它异步调用它的内部方法。我会看看你提供的链接。这段代码有一个竞态条件,如果两个线程在检查另一个线程是否完成之前同时将done标志设置为true,FinishMethod将被调用两次。我曾想过这一点,但我不确定如何防止它。我对多线程不太熟悉。不难修复,只要在每个方法周围加上一个锁,这样就可以原子地设置完成标志和检查另一个完成标志。为了确保不会永远阻塞,请使用