我有一个同步工作的 .NET 4.5 WCF 客户端。我正在更新它以使用新的异步/等待功能来同时进行多个服务器调用以同时获取数据块。
在我完成之前,我担心同时运行的所有线程都会使服务器饱和(更不用说在我明年升级到该角色时杀死我的 Azure 工作者角色)。有没有办法集中管理我在类级别使用的任务线程的总量?该代码与其他 WCF 客户端代码共享一个程序集。
感谢所有的想法。
我有一个同步工作的 .NET 4.5 WCF 客户端。我正在更新它以使用新的异步/等待功能来同时进行多个服务器调用以同时获取数据块。
在我完成之前,我担心同时运行的所有线程都会使服务器饱和(更不用说在我明年升级到该角色时杀死我的 Azure 工作者角色)。有没有办法集中管理我在类级别使用的任务线程的总量?该代码与其他 WCF 客户端代码共享一个程序集。
感谢所有的想法。
从字面上回答您的问题:您可以通过实现自己的TaskScheduler并将其分配给您创建的每个任务来控制用于处理任务的线程数。微软甚至有一个完整的例子。
但是,要回答根本问题:Task
并不意味着Thread
. 事实上,async/await 的主要目标是减少应用程序中的线程数。实际上,可以围绕 async/await 和 Tasks 设计一个完整的应用程序,运行数千个并发任务,只使用一个线程。
您希望您的代码在尽可能少的线程中运行,理想情况下不超过您拥有的逻辑 CPU 的数量,并且您希望 I/O 与您的代码同时发生。操作系统可以为您管理所有 I/O,而无需创建额外的线程。任务可帮助您完成此任务。
它可以为每个任务创建一个线程的唯一时间是如果您正在模拟异步性,例如。调用 Task.Run 运行阻塞代码。这种代码确实是不明智的:
Task t1 = Task.Run(()=>DownloadFile(url1));
Task t2 = Task.Run(()=>DownloadFile(url2));
await Task.WhenAll(t1, t2)
真正的异步代码(可以在单线程中运行)要好得多,例如:
Task t1 = DownloadFileAsync(url1);
Task t2 = DownloadFileAsync(url2);
await Task.WhenAll(t1, t2)
或者,对于任意数量的任务:
List<Task> tasks = new List<Task>();
foreach(string url in urls)
{
tasks.Add(DownloadFileAsync(url))
}
await Task.WhenAll(tasks);
In the context of asynchronous WCF servers, there are no "Task threads".
You have Task
instances that represent in-progress requests, but they are not thread pool threads. The server will allocate thread pools as needed to requests that have some work to do; a request that is asynchronously waiting (in an await
) does not have a thread.