C# 启动一个进程,如果其中一个线程占用CPU,则暂停该进程
有一种说法是,Windows 8上的Skype在一些用户的PC上占据了100%的CPU核心。包括我的!有一个:C# 启动一个进程,如果其中一个线程占用CPU,则暂停该进程,c#,.net,visual-c++,process,skype,C#,.net,Visual C++,Process,Skype,有一种说法是,Windows 8上的Skype在一些用户的PC上占据了100%的CPU核心。包括我的!有一个: 下载并运行最新版本的process explorer。() Skype运行时,在活动程序列表中搜索Skype.exe并双击它 转到“线程”选项卡,挂起或杀死空闲时消耗最高资源的Skype线程。(比如50%以上的CPU) 我在每次重启后手动操作这个问题,所以我想把上面的步骤自动化,编写一个简单的C++或C语言的“Skype发射器”程序,程序如下: 启动SKYPE.EXE 每1秒醒来一次
我在每次重启后手动操作这个问题,所以我想把上面的步骤自动化,编写一个简单的C++或C语言的“Skype发射器”程序,程序如下:
- 启动SKYPE.EXE
- 每1秒醒来一次,看看是否有一个特定的Skype线程占用了进程中98%以上的CPU周期
- 如果找到,则挂起该线程并退出启动程序进程
- 否则,最多循环10次,直到找到坏线程李>
在快速的谷歌搜索之后,我被Win32线程枚举API吓坏了,而这个“查找并杀死/挂起邪恶线程”的问题似乎相当普遍,所以我想知道是否有一个现有的示例可以重复使用。有什么建议吗?在经过更多的谷歌搜索和powershell(太多的安全问题,对新手来说太混乱)和WMI(比需要的更难)的一些死胡同后,我终于找到了一个很好的解决方案。这很容易适应在挂起罪犯之前首先检查每个线程的CPU时间 这是代码。只需编译并进入您的启动菜单,Skype将不再加热您的办公室
// code adapted from
// http://social.msdn.microsoft.com/Forums/en-US/d51efcf0-7653-403e-95b6-bf5fb97bf16c/suspend-thread-of-a-process
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using System.ComponentModel;
namespace SkypeLauncher
{
class Program
{
static void Main(string[] args)
{
Process[] procs = Process.GetProcessesByName("skype");
if (procs.Length == 0)
{
Console.WriteLine("Skype not loaded. Launching. ");
Process.Start(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES(X86)%\Skype\Phone\Skype.exe"));
Thread.Sleep(8000); // wait to allow skype to start up & get into steady state
}
// wait to allow skype to start up & get into steady state, where "steady state" means
// a lot of threads created
Process proc = null;
for (int i = 0; i < 50; i++)
{
procs = Process.GetProcessesByName("skype");
if (procs != null)
{
proc = procs[0];
if (proc.Threads.Count > 10)
break;
}
Thread.Sleep(1000); // wait to allow skype to start up & get into steady state
}
// try multiple times; if not hanging after a while, give up. It must not be hanging!
for (int i = 0; i < 50; i++)
{
// must reload process to get updated thread time info
procs = Process.GetProcessesByName("skype");
if (procs.Length == 0)
{
Console.WriteLine("Skype not loaded. Exiting. ");
return;
}
proc = procs[0];
// avoid case where exception thrown if thread is no longer around when looking at its CPU time, or
// any other reason why we can't read the time
var safeTotalProcessorTime = new Func<ProcessThread, double> (t =>
{
try { return t.TotalProcessorTime.TotalMilliseconds; }
catch (InvalidOperationException) { return 0; }
}
);
var threads = (from t in proc.Threads.OfType<ProcessThread>()
orderby safeTotalProcessorTime(t) descending
select new
{
t.Id,
t.ThreadState,
TotalProcessorTime = safeTotalProcessorTime(t),
}
).ToList();
var totalCpuMsecs = threads.Sum(t => t.TotalProcessorTime);
var topThread = threads[0];
var nextThread = threads[1];
var topThreadCpuMsecs = topThread.TotalProcessorTime;
var topThreadRatio = topThreadCpuMsecs / nextThread.TotalProcessorTime;
// suspend skype thread that's taken a lot of CPU time and
// and it has lots more CPU than any other thread.
// in other words, it's been ill-behaved for a long time!
// it's possible that this may sometimes suspend the wrong thread,
// but I haven't seen it break yet.
if (topThreadCpuMsecs > 10000 && topThreadRatio > 5)
{
Console.WriteLine("{0} bad thread. {0:N0} msecs CPU, {1:N1}x CPU than next top thread.",
topThread.ThreadState == System.Diagnostics.ThreadState.Wait ? "Already suspended" : "Suspending",
topThreadCpuMsecs,
topThreadRatio);
Thread.Sleep(1000);
IntPtr handle = IntPtr.Zero;
try
{
//Get the thread handle & suspend the thread
handle = OpenThread(2, false, topThread.Id);
var success = SuspendThread(handle);
if (success == -1)
{
Win32Exception ex = new Win32Exception(Marshal.GetLastWin32Error());
Console.WriteLine(ex.Message);
}
Console.WriteLine("Exiting");
Thread.Sleep(1000);
return;
}
finally
{
if (handle != IntPtr.Zero)
CloseHandle(handle);
};
}
Console.WriteLine("Top thread: {0:N0} msecs CPU, {1:N1}x CPU than next top thread. Waiting.",
topThreadCpuMsecs,
topThreadRatio);
Thread.Sleep(2000); // wait between tries
}
Console.WriteLine("No skype thread is ill-behaved enough. Giving up.");
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern
IntPtr OpenThread(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)]bool bInheritHandle, int dwThreadId);
}
}
//改编自
// http://social.msdn.microsoft.com/Forums/en-US/d51efcf0-7653-403e-95b6-bf5fb97bf16c/suspend-thread-of-a-process
使用制度;
使用System.Linq;
使用System.Threading.Tasks;
使用System.Runtime.InteropServices;
使用系统诊断;
使用系统线程;
使用系统组件模型;
命名空间SkypeLauncher
{
班级计划
{
静态void Main(字符串[]参数)
{
Process[]procs=Process.getProcessByName(“skype”);
如果(procs.Length==0)
{
Console.WriteLine(“Skype未加载。正在启动”);
Process.Start(Environment.ExpandEnvironmentVariables(@“%PROGRAMFILES(X86)%\Skype\Phone\Skype.exe”);
Thread.Sleep(8000);//等待skype启动并进入稳定状态
}
//等待skype启动并进入稳定状态,“稳定状态”的意思是
//创建了很多线程
processproc=null;
对于(int i=0;i<50;i++)
{
procs=Process.getProcessByName(“skype”);
如果(procs!=null)
{
proc=procs[0];
如果(proc.Threads.Count>10)
打破
}
Thread.Sleep(1000);//等待skype启动并进入稳定状态
}
//尝试多次;如果一段时间后没有挂起,就放弃。一定不要挂起!
对于(int i=0;i<50;i++)
{
//必须重新加载进程才能获得更新的线程时间信息
procs=Process.getProcessByName(“skype”);
如果(procs.Length==0)
{
Console.WriteLine(“Skype未加载。正在退出”);
返回;
}
proc=procs[0];
//避免在查看线程的CPU时间时,如果线程不再存在而引发异常,或者
//还有其他我们看不到时间的原因吗
var safeTotalProcessorTime=新函数(t=>
{
请尝试{return t.TotalProcessorTime.totalMillistics;}
捕获(InvalidOperationException){返回0;}
}
);
var threads=(来自proc.threads.OfType()中的t)
orderby safeTotalProcessorTime(t)递减
选择新的
{
t、 身份证,
t、 ThreadState,
TotalProcessorTime=安全TotalProcessorTime(t),
}
).ToList();
var totalCpuMsecs=threads.Sum(t=>t.TotalProcessorTime);
var topThread=线程[0];
var nextThread=threads[1];
var topThreadCpuMsecs=topThread.TotalProcessorTime;
var topThreadRatio=topThreadCpuMsecs/nextThread.TotalProcessorTime;
//挂起占用大量CPU时间和内存的skype线程
//而且它的CPU比任何其他线程都多。
//换句话说,它已经坏了很长时间了!
//这可能有时会挂起错误的线程,
//但我还没看到它坏掉。
如果(topThreadCpuMsecs>10000&&topThreadRatio>5)
{
WriteLine(“{0}个坏线程。{0:N0}毫秒CPU,{1:N1}个CPU比下一个顶级线程长。”,
topThread.ThreadState==System.Diagnostics.ThreadState.Wait?“已挂起”:“挂起”,
topThreadCpuMsecs,
顶丝率);
睡眠(1000);
IntPtr handle=IntPtr.Zero;
尝试
{
//获取线程句柄并挂起线程
handle=OpenThread(2,false,topThread.Id);
var success=SuspendThread(句柄);
如果(成功==-1)