我在不是异步页面的页面中使用以下基于任务的编程(TPL).
我的问题是:使用TPL(即任务并行库)在ASP.Net页面中创建多线程调用是否可以,或者必须始终在ASP.Net页面中使用内置的异步页面功能进行多线程处理?到目前为止,TPL方法没有产生任何问题,但只是想确保我在ASP.Net页面中使用TPL时遗漏了一些重要的点/隐藏风险.
Task.Factory.StartNew(() =>
{
try
{
Method1();
success4 = true;
}
catch (Exception e4)
{
success4 = false;
ex = e4.ToString();
}
}),
Task.Factory.StartNew(() =>
{
try
{
Method2();
success5 = true;
}
catch (Exception e5)
{
success5 = false;
ex = e5.ToString();
}
}),
Task.Factory.StartNew(() =>
{
try
{
Method3();
success6 = true;
}
catch (Exception e6)
{
success6 = false;
ex = e6.ToString();
}
})
};
Task.WaitAll(tasks);
更新1:
正如在答案中指出的那样,在ASP.Net中使用TPL会限制ASP.Net应用程序的可伸缩性,因为每个任务都使用来自ASP.Net线程池的线程,同时保持页面的原始线程在封锁状态.
我正在考虑在Async页面中调用方法时使用TPL,如下面的代码所示,以利用并行性带来的更强大的处理.但我会进一步研究这一点,看看在实际情况下,TPL是否会使异步方法更好或更差.
private void DoTask4(object[] paras)
{
Parallel.Invoke(() =>
{
try
{
Method4( paras);
}
catch (Exception e4)
{
success4 = false;
//log the exception
}
});
}
IAsyncResult BeginAsyncOperation4(object sender, EventArgs e, AsyncCallback cb, object state)
{
task4 = new AsyncTaskDelegate(DoTask4);
IAsyncResult result = task4.BeginInvoke(state as object[], cb, "task4");
return result;
}
void EndAsyncOperation4(IAsyncResult ar)
{
task4.EndInvoke(ar);
if (success4 == null)
{
success4 = true;
}
}
void TimeoutAsyncOperation4(IAsyncResult ar)
{
success4 = false;
}
更新2:
最后,正如答案中所指出的,即使使用TPL和Async页面方法也会导致线程池中的线程被使用,这再次意味着我们的ASP.Net可伸缩性将成为一个问题.
因此,最好不要在Async页面中使用TPL.
最佳答案 这种方法可能严重损害服务器的可伸缩性,因为它使用额外的theads并阻塞请求线程.假设Method1..3负责一些IO绑定工作.如果您不能使用异步ASP.NET控制器,您仍然可以使用AsyncManager(例如,像
this)或
PageAsyncTask
(对于经典ASP.NET)启动异步IO绑定操作并避免阻塞.
但是,如果你需要做一些CPU绑定工作(而不是IO绑定工作),只需在同一个请求线程上,一步一步,而不是并行执行.否则,每个Task.Factory.StartNew可能会暂停另一个传入的HTTP请求,具体取决于服务器负载.因为您可能希望尽可能多地提供并发HTTP请求,所以应避免并行化CPU绑定工作.
也就是说,您的代码可能适用于并发HTTP请求数较少的Intranet Web应用程序.如果您想加快单个请求的响应传递,则可以这样做.