Asp.net 使用Task::run()在单独的线程中运行整个HTTP操作方法有多糟糕?
我正在使用Microsoft的web API以C++/CLI(不是我的选择)编写web服务。WebAPI中的许多函数都是异步的,但是因为我使用的是C++/CLI,所以我没有得到C#或VB的异步/等待支持。因此,备用位置是用来安排一个延续委托,以便安全地读取异步任务的结果 但是,由于C++/CLI也不支持内联匿名委托或托管lambda,因此每个委托延续必须作为单独的函数写入某个位置。随着Web API中异步函数的数量增加,这很快就会变成意大利面条 因此,为了避免出现Asp.net 使用Task::run()在单独的线程中运行整个HTTP操作方法有多糟糕?,asp.net,.net,asynchronous,asp.net-web-api,c++-cli,Asp.net,.net,Asynchronous,Asp.net Web Api,C++ Cli,我正在使用Microsoft的web API以C++/CLI(不是我的选择)编写web服务。WebAPI中的许多函数都是异步的,但是因为我使用的是C++/CLI,所以我没有得到C#或VB的异步/等待支持。因此,备用位置是用来安排一个延续委托,以便安全地读取异步任务的结果 但是,由于C++/CLI也不支持内联匿名委托或托管lambda,因此每个委托延续必须作为单独的函数写入某个位置。随着Web API中异步函数的数量增加,这很快就会变成意大利面条 因此,为了避免出现Task::Result的问题,
Task::Result
的问题,我一直在尝试以下方法:
[HttpGet, Route( "get/some/dto" )]
Task< SomeDTO ^ > ^ MyActionMethod()
{
return Task::Run( gcnew Func< SomeDTO ^ >( this, &MyController::MyActionMethod2 ) );
}
SomeDTO ^ MyActionMethod2()
{
// execute code and use any task->Result calls I need without deadlocking
}
[HttpGet,Route(“get/some/dto”)]
任务^MyActionMethod()
{
返回任务::运行(gcnewfunc(this,&MyController::MyActionMethod2));
}
SomeDTO^MyActionMethod2()
{
//执行代码并使用我需要的任何任务->结果调用,无需死锁
}
好吧,我知道这不太好,但有多糟?我对Web API或ASP.NET的胆识还不够了解,无法理解这将带来的性能或扩展后果
此外,这可能会产生哪些与性能无关的其他后果?例如,异常被包装在一个额外的AggregateException中,这表示处理异常的额外复杂性和工作量。您的内存使用将随着应用程序的并行性而增加。对于对
MyActionMethod
的每次并发调用,您都需要一个具有自己堆栈的独立线程。这将为每个并发调用花费大约1MB的RAM。如果MyActionMethod
运行的时间足够长,一次可以运行10000个实例,那么您将看到10GB的RAM。在设置每个线程时还存在CPU开销
如果并发性较低,则放弃异步支持不会成为问题。在这种情况下,不要费心于Task::Run
。只需更改MyActionMethod
以返回SomeDTO^
(无Task
wrapper)
另一个潜在的问题是取消令牌的易用性。然而,对于WebAPI来说,通常可以让异常传播回WebAPI,这最终会取消同步调用
最后,如果您计划并行执行action方法中的任何操作,您仍然需要使用
ContinueWith
来完成。默认情况下,非异步意味着您总是一次执行一个操作。幸运的是,这样做通常没什么问题。应用程序的并行性会增加内存使用量。对于对MyActionMethod
的每次并发调用,您都需要一个具有自己堆栈的独立线程。这将为每个并发调用花费大约1MB的RAM。如果MyActionMethod
运行的时间足够长,一次可以运行10000个实例,那么您将看到10GB的RAM。在设置每个线程时还存在CPU开销
如果并发性较低,则放弃异步支持不会成为问题。在这种情况下,不要费心于Task::Run
。只需更改MyActionMethod
以返回SomeDTO^
(无Task
wrapper)
另一个潜在的问题是取消令牌的易用性。然而,对于WebAPI来说,通常可以让异常传播回WebAPI,这最终会取消同步调用
最后,如果您计划并行执行action方法中的任何操作,您仍然需要使用
ContinueWith
来完成。默认情况下,非异步意味着您总是一次执行一个操作。幸运的是,这样做通常没什么问题。应用程序的并行性会增加内存使用量。对于对MyActionMethod
的每次并发调用,您都需要一个具有自己堆栈的独立线程。这将为每个并发调用花费大约1MB的RAM。如果MyActionMethod
运行的时间足够长,一次可以运行10000个实例,那么您将看到10GB的RAM。在设置每个线程时还存在CPU开销
如果并发性较低,则放弃异步支持不会成为问题。在这种情况下,不要费心于Task::Run
。只需更改MyActionMethod
以返回SomeDTO^
(无Task
wrapper)
另一个潜在的问题是取消令牌的易用性。然而,对于WebAPI来说,通常可以让异常传播回WebAPI,这最终会取消同步调用
最后,如果您计划并行执行action方法中的任何操作,您仍然需要使用
ContinueWith
来完成。默认情况下,非异步意味着您总是一次执行一个操作。幸运的是,这样做通常没什么问题。应用程序的并行性会增加内存使用量。对于对MyActionMethod
的每次并发调用,您都需要一个具有自己堆栈的独立线程。这将为每个并发调用花费大约1MB的RAM。如果MyActionMethod
运行的时间足够长,一次可以运行10000个实例,那么您将看到10GB的RAM。在设置每个线程时还存在CPU开销
如果并发性较低,则放弃异步支持不会成为问题。在这种情况下,不要费心于Task::Run
。只需更改MyActionMethod
以返回SomeDTO^
(无Task
wrapper)
另一个潜在的问题是取消令牌的易用性。然而,对于WebAPI来说,通常可以让异常传播回WebAPI,这最终会取消同步调用
最后,如果您计划并行执行action方法中的任何操作,您仍然需要使用Cont