在c#中使用IIS托管WCF服务进行任务管理
本文关键字:服务 WCF 任务管理 托管 IIS | 更新日期: 2023-09-27 18:18:39
我在IIS中托管了32位版本的WCF服务。其中,我使用以下方法创建任务以并行执行我的操作(处理数据库计算或向第三方进行外部调用)。
List<Task> taskList = new List<Task>();
Task parentTask = Task.Factory.StartNew(() =>
{
for (int i = 0; i <= 5; i++)
{
var task = new Task(() => Do(), TaskCreationOptions.AttachedToParent);
taskList.Add(task);
}
});
foreach (Task t in taskList)
{
t.Start();
}
parentTask.Wait(20000);
使用上面的代码,我创建了大约140个任务,其中包含对我的服务的单个请求。我的应用程序每秒大约有10个请求。我面临的问题是,大多数任务在我的父线程等待之前没有执行,当它要执行繁重的操作时,任务没有得到足够的CPU意味着没有调用并行任务。
我只是想知道处理多线程的最好方法是什么。我在很多文章中看到task . factory . startnew总是使用线程池的概念,为什么我的任务在高并发请求下启动和运行需要超过20秒的时间。
在本例中,我假设所有操作都在父节点等待结束之前完成。这是取消任务而不是等待的最佳方式吗?
32位应用程序和64位应用程序对。net framework 4.0的任务管理有重要影响吗?
提前感谢!!
总有"最好的方法"。在你的情况下,试试
taskList.WaitAll ();代替parentTask.Wait(20000);
32位应用程序和64位应用程序对。net framework 4.0的任务管理有重要影响吗?
答案是否定的。任务在线程池线程上执行。无论CPU运行的是32位进程还是64位进程,它一次只能执行一个线程。线程池的大小可以调整,但不建议这样做。. net框架通过一个复杂的计算来确定线程池的大小,这是基于cpu/内核的数量、时钟速度和其他一些参数。
同时执行太多的线程是不高效的,因为管理和切换线程需要资源。如果你有一堆CPU绑定的线程都排队,那么大量的CPU时间可以在它们之间来回切换,并且永远不会完成任何工作(有点像你每10分钟有7个项目经理在你的办公桌前停下来询问状态更新),导致更多的线程被创建,因为更多的工作被请求,直到你的服务器100%挂起并停止工作。
既然父任务应该等待子任务,那么你应该使用任务类的WaitAll
方法,等待所有提供的任务对象完成执行。
创建示例程序来演示相同的内容:
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Console.WriteLine("Starting Parent Task");
List<Task> taskList = new List<Task>();
Task parentTask = Task.Factory.StartNew(() =>
{
for (int i = 0; i <= 5; i++)
{
var task = new Task(() => Console.WriteLine("Task Running : " + Task.CurrentId), TaskCreationOptions.AttachedToParent);
taskList.Add(task);
}
foreach (Task t in taskList)
{
t.Start();
}
Task.WaitAll(taskList.ToArray());
});
Console.WriteLine("Parent Task Ending");
}
}
创建这个。net提琴。您可以查看它的输出
我想你已经读过这个了(https://msdn.microsoft.com/en-us/library/dd997417.aspx)。如果您不使用附加任务方法(异常和取消传播)提供的任何功能,您可以这样做,如Atom刚才建议的taskList.WaitAll(20000)。但是请记住,如果没有显式地实现取消,那么在这个Wait()完成之后,您的任务仍在运行。
Do()
是多少也很重要。任务正在使用ThreadPool,您可以管理其中的线程数量。您可以指定其中的线程数。如果你的Do()
是计算,你总是使用工作线程。但是如果在这个调用中您使用了另一个服务,您应该异步执行。这样,您将使用I/O完成端口和适当的I/O线程,这几乎不消耗任何系统资源。要异步运行服务调用,您可以使用带有Task result或Begin/End+IAsyncResult的客户端方法的异步版本。在第二种情况下,你可以使用TaskFactory。