[英]Infinite loop in task - cpu usage
我正在為某些控制器數據提供監視服務,如果發生更改,則將其寫入數據庫。 看起來很簡單。 以前,我在Delphi中實現了同樣的目的,但是現在我在C#(.Net 4.5)上。 現在,服務可以很好地處理100個任務,但會占用大約7-8%的CPU時間。 我的Delphi服務吃了大約0%。 如何減少CPU占用哪種服務的時間? PS:每個任務都有自己的類實例,可以連接並插入數據庫並使用數據的本地副本。
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);
}
最近,我遇到了一個類似的難題,並通過使用一組專用的長期運行任務來在我的應用程序中執行異步工作,從而設法解決了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
此圖顯示了相同工作負載(上午9點后顯示)在CPU使用率方面的差異。
因此,我認為通過使用上述專用/長期運行的任務來繞過線程池可以在某些情況下提高CPU利用率。 它肯定是在我的:-)
我移至計時器說明,因為它是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);
}
}
我進入了內部無限循環的基本線程。 它可以滿足我的需求。 無需大量重新創建/重新啟動等操作。 現在,它像Delphi服務一樣運作良好,但在處理數據和DB時卻更加舒適。 我從lambda new thread()=>通過此過程啟動線程:
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);
}
}
有兩種特殊的技術可以幫助減少長時間循環等待中的CPU使用率。 一種是使用線程睡眠方法。 例如,這在獨立應用程序中很好,而在Windows服務中則更少。
在服務中,第二,您應該使用計時器。 這些以固定間隔觸發,因此在間隔之間不請求CPU。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.