任务中的无限循环 - cpu使用

时间:2015-02-19 13:06:20

标签: c# async-await task infinite-loop cpu-usage

我正在为某些控制器数据进行监视服务,如果它发生变化,我会将其写入数据库。看似简单。我普遍认识到与Delphi相同,但现在我在C#(.Net 4.5)。现在服务可以很好地完成100个任务,但占用大约7-8%的CPU时间。我的Delphi服务大约占0%。 如何减少CPU使用服务的时间? P.S。:每个任务都有自己的类来连接和插入数据库并使用本地数据副本。

int TagCnt = DataCtrl.TagList.Count;                     
    stopExec = false;
    if (TagCnt != 0)
    {                
        tasks = new Task[TagCnt];                
        for (int i = 0; i <= TagCnt - 1; i++)
        {                    
            int TempID = i;
            tasks[TempID] = Task.Run(async () => // make threads for parallel read-write tasks // async
            {                                            
                Random rand = new Random();
                TimeSpan delay = TimeSpan.FromMilliseconds(rand.Next(1000, 1500))                                              
                try
                {
                    while (!stopExec)
                    {                               
                    cToken.ThrowIfCancellationRequested();                          
                    //do basic job here
                    await Task.Delay(delay, cToken);
                    }//while end                            
                }
                catch (...)
                {
                ...
                }                                            
            }, cToken);                   
        }

4 个答案:

答案 0 :(得分:0)

最近我遇到了类似的难题,并设法通过使用一组专用的长期运行任务来解决不稳定的CPU使用情况,以便在我的应用程序中执行异步工作,如下所示:

    Dim NumThreads As Integer = 10
    Dim CanTokSrc As New CancellationTokenSource
    Dim LongRunningTasks As Task() = New Task(NumThreads) {}
    Dim i As Integer
    Do Until i = LongRunningTasks.Count
        LongRunningTasks(i) = Task.Factory.StartNew(Sub()
                                                        Do Until CanTokSrc.IsCancellationRequested
                                                            'DO WORK HERE
                                                        Loop
                                                    End Sub, CanTokSrc.Token, TaskCreationOptions.LongRunning)
        i = i + 1
    Loop

This image显示了相同工作负载在CPU使用率方面的差异(显示在上午9点之后)。

因此,我认为通过使用上述专用/长时间运行的任务绕过线程池可以在某些情况下提高CPU利用率。它当然在我的: - )

答案 1 :(得分:0)

我转移到计时器指令,因为它是一个Windows服务。定时器负载的每个事件大约是7-10%,介于0%之间。我试图应用任务,ThreadSchedule - 它们似乎更重。

 private void OnReadTimer(object source, ElapsedEventArgs e) //check states on timer
    {
        int TagCnt = DataCtrl.TagList.Count;
        po.MaxDegreeOfParallelism = DataCtrl.TagList.Count;
        // string ss = "tags=" + TagCnt;
        //int TempID;
        Random rand = new Random();
        try
        {
            if (TagCnt != 0)
            {                    
                ParallelLoopResult loopResult = Parallel.For(0, TagCnt - 1, po, (i, loopState) =>
                {
                    po.CancellationToken.ThrowIfCancellationRequested();
                    int TempID = i;
                    Thread.Sleep(rand.Next(100, 200));
                    int ID = 0;
                    bool State = false;
                    long WT = 0;
                    int ParID = 0;
                    bool Save = false;                        
                    ReadStates(TempID, out ID, out State, out WT, out ParID, out Save);
                    lock (locker)
                    {
                        if (Save) WriteState(ID, State, WT, ParID);
                    }
                });
            }


        }
        catch (TaskCanceledException)
        {
        }
        catch (System.NullReferenceException eNullRef)
        {
            AddLog("Error:" + eNullRef);
        }
        catch (System.ArgumentOutOfRangeException e0)
        {
            AddLog("Error:" + e0);
        }
        catch (Exception e1)
        {
            //AddLog("Error while processing data: " + e1);
        }
    }

答案 2 :(得分:0)

我移动到内部有无限循环的基本线程。它可以满足我的需求。没有繁重的重建/重启等等。现在它像Delphi服务一样工作得很好,但是数据和数据库的工作更加舒适。我从lambda new thread()=&gt;:

开始使用此过程的线程
        void RWDeviceState(int i)
    {
        try
        {
            int TempID = i;
            long StartTime;
            long NextTime;
            long Period = 3000;
            int ID = 0;
            bool State = false;
            long WT = 0;
            int ParID = 0;
            bool Save = false;                
            while (ExecutionAllowed)
            {
                Save = false;
                ReadStates(TempID, out ID, out State, out WT, out ParID, out Save);
                lock (locker)
                {
                    if (Save) WriteState(ID, State, WT, ParID);
                }
                StartTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                NextTime = StartTime + Period;
                while (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond < NextTime && ExecutionAllowed)
                {
                    Thread.Sleep(40);
                }
            }

答案 3 :(得分:-2)

有两种特殊技术可以帮助减少长循环等待中的CPU使用率。一,是使用线程睡眠方法。例如,在独立应用程序中,这在Windows服务中较少。

在服务中,对于第二种,您应该使用计时器。它们会定期触发,因此在间隔期间不会请求CPU。