Nid*_*dhi 44 c# performance system.diagnostics cpu-usage
最近,我在构建我的程序时变得更加健康,我观察到大多数程序需要2或3分钟才能执行,当我检查任务调度程序时,我发现它们消耗了100%的CPU使用率,可以我在代码中以编程方式限制了这种用法?这肯定会让我在给定的时间运行多个程序.
谢谢,Nidhi
Rya*_*yan 81
这个帖子已经超过四年了,我仍然很恼火,接受的答案批评这个问题而不是回答它.有许多有效的理由要限制程序占用的CPU时间,我可以列出一些我的头脑.
不使用所有可用的CPU周期似乎是浪费,但这种心态是有缺陷的.与较旧的CPU不同,大多数现代CPU不以固定的时钟速度运行 - 许多都具有省电模式,在负载较低时它们会降低时钟速度和CPU电压.执行计算时CPU也会比运行NOOP时消耗更多功率.这与需要风扇在高负载时冷却CPU的笔记本电脑尤其相关.在短时间内以100%运行任务可以比使用25%的任务执行任务多四倍的能量.
想象一下,您正在编写一个后台任务,旨在定期在后台索引文件.索引任务是否应该以较低的优先级使用尽可能多的CPU,或者将自己限制在25%并且需要多长时间?好吧,如果要在笔记本电脑上消耗100%的CPU,CPU就会升温,风扇会启动,电池会很快耗尽,用户会感到恼火.如果索引服务自身受到限制,笔记本电脑可能能够以非常低的CPU时钟速度和电压完全被动冷却.
顺便提一下,Windows索引服务现在会在较新版本的Windows中限制自己,这在旧版本中从未发生过.有关仍然不会限制自身且经常使人烦恼的服务示例,请参阅Windows Installer模块.
如何在C#内部限制部分应用程序的示例:
public void ThrottledLoop(Action action, int cpuPercentageLimit) {
Stopwatch stopwatch = new Stopwatch();
while(true) {
stopwatch.Reset();
stopwatch.Start();
long actionStart = stopwatch.ElapsedTicks;
action.Invoke();
long actionEnd = stopwatch.ElapsedTicks;
long actionDuration = actionEnd - actionStart;
long relativeWaitTime = (int)(
(1/(double)cpuPercentageLimit) * actionDuration);
Thread.Sleep((int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000));
}
}
Run Code Online (Sandbox Code Playgroud)
Sho*_*og9 30
这不是您关心的问题......操作系统的工作是在运行的进程之间分配处理器时间.如果你想让其他进程首先完成他们的工作,那么只需通过修改Process.PriorityClass它的值来降低自己进程的优先级.
Mar*_*arc 20
首先,我同意Ryan的看法,这个问题是完全有效的,并且有些情况下线程优先级根本不够.其他答案看起来非常理论化,在应用程序设计合理但仍需要加以限制的情况下没有实际用途.Ryan为在高频率下执行相对较短任务的情况提供了简单的解决方案.但是,有些情况下,当任务需要很长时间(比如一分钟左右)时,您不能或不想将其分成较小的块,在这些块之间可以进行限制.对于这些情况,以下解决方案可能会有所帮助
而不是在业务代码中实施限制,您可以将算法本身设计为全速工作,并简单地限制"从外部"运行操作的线程.一般方法与Ryan的答案相同:根据当前使用情况计算暂停时间,并在再次恢复之前暂停该时间跨度.给定一个您想要限制的进程,这是逻辑:
public static class ProcessManager
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int CloseHandle(IntPtr hThread);
public static void ThrottleProcess(int processId, double limit)
{
var process = Process.GetProcessById(processId);
var processName = process.ProcessName;
var p = new PerformanceCounter("Process", "% Processor Time", processName);
while (true)
{
var interval = 100;
Thread.Sleep(interval);
var currentUsage = p.NextValue() / Environment.ProcessorCount;
if (currentUsage < limit) continue;
var suspensionTime = (currentUsage-limit) / currentUsage * interval;
SuspendProcess(processId);
Thread.Sleep((int)suspensionTime);
ResumeProcess(processId);
}
}
private static void SuspendProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
SuspendThread(pOpenThread);
CloseHandle(pOpenThread);
}
}
private static void ResumeProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
var suspendCount = 0;
do
{
suspendCount = ResumeThread(pOpenThread);
} while (suspendCount > 0);
CloseHandle(pOpenThread);
}
}
}
Run Code Online (Sandbox Code Playgroud)
此解决方案的好处是检查间隔与"长时间运行的任务"的持续时间无关.此外,业务逻辑和限制逻辑是分开的.悬念/简历代码的灵感来自于这个主题.请注意,处理和结束限制需要在上面的解决方案中实现,它不是生产代码.
mal*_*mal 15
您可以编写一个Governor限制CPU使用率的类.该类将包含一个实用程序方法,该方法应该由CPU绑定函数定期调用(例如,在函数的while循环中调用此实用程序函数).调控器将检查经过的时间量是否超过特定阈值,然后休眠一段时间以便不消耗所有CPU.
这是一个简单的Java实现,如果您有一个单独的线程CPU绑定功能,那么可以将CPU使用率限制为50%.
public class Governor
{
long start_time;
public Governor()
{
this.start_time = System.currentTimeMillis();
}
public void throttle()
{
long time_elapsed = System.currentTimeMillis() - this.start_time;
if (time_elapsed > 100) //throttle whenever at least a 100 millis of work has been done
{
try { Thread.sleep(time_elapsed); } catch (InterruptedExceptione ie) {} //sleep the same amount of time
this.start_time = System.currentTimeMillis(); //reset after sleeping.
}
}
}
Run Code Online (Sandbox Code Playgroud)
您的CPU绑定函数将实例化a Governor,然后throttle在函数内定期调用.
谢谢大家的回答。我一直在研究这个,它运行了几个小时的 exe 并希望分享以帮助他人。我写了一个类,我将在一个 WPF 应用程序中设置并忘记它,该应用程序将加密并将数据推送到云,但我永远不会让它干扰 WPF 应用程序的时间以及 WPF 应用程序需要什么在资源方面,当 WPF 应用程序处于最高资源消耗状态时,我还将添加一个标志以禁用。我已经用 TPL 高度线程化了这个 WPF。此解决方案具有进程的优先级集
myProcess.PriorityClass = ProcessPriorityClass.Idle;
Run Code Online (Sandbox Code Playgroud)
并且 CPU 百分比有限。
然后在我的 mainDisplay.xaml.cs 中我将使用
ProcessManagement.StartProcess(5);
Run Code Online (Sandbox Code Playgroud)
在主窗口()
并且运行该exe时没有弹出窗口
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
Run Code Online (Sandbox Code Playgroud)
在对象初始化器中
internal class ProcessManagement
{
private static int CpuPercentageLimit { get; set; }
public static void StartProcess(int cpuPercent)
{
CpuPercentageLimit = cpuPercent;
var stopwatch = new Stopwatch();
while (true)
{
stopwatch.Reset();
stopwatch.Start();
var actionStart = stopwatch.ElapsedTicks;
try
{
var myProcess = new Process
{
StartInfo =
{
FileName = @"D:\\Source\\ExeProgram\\ExeProgram\\bin\\Debug\\ExeProgram.exe",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
myProcess.Start();
myProcess.PriorityClass = ProcessPriorityClass.Idle;
myProcess.Refresh();
myProcess.WaitForExit();
var actionEnd = stopwatch.ElapsedTicks;
var actionDuration = actionEnd - actionStart;
long relativeWaitTime = (int)((1 / (double)CpuPercentageLimit) * actionDuration);
var sleepTime = (int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000);
Thread.Sleep(sleepTime);
myProcess.Close();
}
catch (Exception e)
{
// ignored
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的应用程序中,有足够的时间(例如 24/7/365)上传大量数据,包括数千张图像,但 UI 也需要在使用时保持活动状态,并且当系统运行时,没有其他东西可以运行。
| 归档时间: |
|
| 查看次数: |
33050 次 |
| 最近记录: |