在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的任务管理有重要影响吗?

提前感谢!!

在c#中使用IIS托管WCF服务进行任务管理

总有"最好的方法"。在你的情况下,试试

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。