流程操作(监视)
本文关键字:监视 操作 程操作 | 更新日期: 2023-09-27 18:33:42
我想在我的程序中完成的是知道某些进程是否正在运行(我需要知道所有正在运行的实例(。我想将它们放在组合框中,存储为对象,以便以后可以将它们投射回来。我以为这很容易,但事实证明,这让我有些头疼:P我不确定这是否应该这样做,但它正在工作。但是,我对这个代码解决方案感觉很糟糕。我不知道有什么好的编程模式,这就是为什么我请你们的程序员来帮助我。
我想到的第一件事是使用计时器频繁地检查进程并添加它们,并使用 Exited 事件将它们从我的组合框中删除。所以这是我在计时器的 Tick 事件上的代码:
private void timer_ProcessCheck_Tick(object sender, EventArgs e)
{
Process[] tmpArray = Wow_getCurrentlyRunning(); // this returns Process[]
if (comboBox_processes.Items.Count == 0)
{
if (tmpArray.Count() > 0)
for (int Index = 0; Index < tmpArray.Count(); Index++)
Add(tmpArray[Index]); // adding to combobox
}
else
{
if (tmpArray.Count() > comboBox_processes.Items.Count)
{
List<Process> result;
/*Diff compares the two array, and returns to result variable.*/
if (Diff(tmpArray, comboBox_processes, out result))
foreach(Process proc in result)
Add(proc); // adding to combobox
}
}
}
我的 Diff 方法看起来像这样,它将把差异放在 diff 变量上。
public bool Wow_differsFrom(Process[] current, ComboBox local, out List<Process> diff)
{
List<int> diffIndex = new List<int>();
foreach (Process proc in current)
diffIndex.Add(proc.Id);
for (byte Índex = 0; Índex < current.Count(); Índex++)
{
for (byte Index = 0; Index < local.Items.Count; Index++)
{
if (current[Índex].Id == (local.Items[Index] as Process).Id)
{
diffIndex.Remove(current[Índex].Id);
break;
}
}
}
diff = new List<Process>();
for (int x = 0; x < current.Count(); x++)
for (int i = 0; i < diffIndex.Count; i++)
if (current[x].Id == diffIndex[i])
diff.Add(current[x]);
if (diff.Count == 0)
return false;
return true;
}
这是在进程退出时调用的 Exited 事件处理程序
private void Wow_exitedEvent(object o, EventArgs e)
{
RemoveCBItem(comboBox_processes, (o as Process).Id); // this will remove the process from combobox, also threadsafe.
}
我的问题 :
你会怎么做?我接近这个对吗?我有一种感觉,我没有。
是否有任何应用程序启动事件?就像有一个 退出。也许深入Win32 API?
总的来说,我认为这个想法是正确的 - 如果您需要每次刷新活动进程的列表。因此,使用计时器更新列表是可以的。我不太了解Win32 API,但我认为如果有人可以订阅process_run和process_retminate wineows事件,这将是一个安全问题,所以这不太可能。
但是你真的需要一直更新它吗?也许只有在组合框扩展时阅读进程列表就足够了?当用户下次展开它时,您将再次重新初始化项目。我认为这种方法会导致更少的问题。
至于您的实现,我认为它不是最有效和最优雅的:
- 将
- 整个 Process 对象存储在组合框项目中对我来说并不好。最好创建您的类,该类将仅存储您需要的属性(进程 ID、进程名称(
使用电流。循环中的 Count(( 效率非常低 - 它是在调用时始终迭代 IEnumerable 的扩展方法。所以你的
对于(字节 Índex = 0;Índex <当前。计数((;Índex++(>
导致 O(N*N( 复杂性。幸运的是,进程计数不会太大,不会对您的应用程序产生太大影响,但您应该知道这一事实,并且不习惯在循环中使用此方法。使用当前。长度,因为它是一个数组。
您的集合同步太复杂和奇怪。为什么不创建一个方法,该方法接收要更改的集合和要从初始化的集合,并使用添加-删除操作使第一个集合等于第二个集合?你们将按某些属性(例如进程名称(对两个集合进行排序,这可以非常简单有效地完成 - 使用二叉搜索。在 WPF 中,可以使用 ObservableCollection 作为数据源来最有效地使用此方法。在 WinForms 中,您可能还可以使用带有更改通知的集合,但我还没有使用它们。
您可以做得更简单:
//Somewhere in Form_Load
combobox.DisplayMember = "Name";//name of the property in your MyProcessInfo class
combobox.ValueMember = "Id";//name of the property in your MyProcessInfo class
//In your timer.Tick handler
combobox.DataSource = Wow_getCurrentlyRunning().Select(p=>new MyProcessInfo(p.Id, p.Name)).ToList();
但是,如果组合框和一些闪烁是可能的,这种方法将始终重新初始化所有项目。