我正在为某些控制器数据进行监视服务,如果它发生变化,我会将其写入数据库。看似简单。我普遍认识到与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);
}
答案 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。