简体   繁体   English

流程操作(监控)

[英]Process Operations (Monitoring)

What I'm trying to accomplish in my program is to knows if certain processes are running (I need to know about all running instances). 我要在程序中完成的任务是知道某些进程是否正在运行(我需要了解所有正在运行的实例)。 I want to hold them in a combobox, store as a object, so I can cast them back later. 我想将它们保存在组合框中,并作为对象存储,以便稍后将其还原。 I thought this will be easy but as it turned out, it caused me some headache :P I'm not sure that this is how it should be done, but it's working. 我以为这很容易,但是事实证明,这让我有些头疼:P我不确定这是应该怎么做的,但是它正在工作。 However, I'm feel bad about this code solution. 但是,我对此代码解决方案感到不满意。 I dont know any good programming patterns for this, this is why I ask you fellow coders, to help me out. 我不知道有什么好的编程模式,这就是为什么我请各位编码员来帮助我。

The first thing came into my mind is to use a timer to check for processes frequentally and add them, and use the Exited event to remove them from my combobox. 我想到的第一件事是使用计时器来频繁检查进程并添加它们,并使用Exited事件将其从我的组合框中删除。 So here is my code on Tick event of the timer : 所以这是我的计时器的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
            }
        }
    }

And my Diff method looks like this, which will put the difference to diff variable. 我的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;
    }  

Here is the Exited event handler get called upon a process exit 这是在流程退出时调用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.
    }

My questions : 我的问题:

  1. How would you do this? 你会怎么做? Am I approaching this right? 我要达到这个权利吗? I have a feeling, I dont. 我有一种感觉,我没有。

  2. Is there any event for application start? 是否有任何启动应用程序的事件? Like there is one for exit. 就像有一个出口。 Maybe deep in Win32 API? 也许深入了解Win32 API?

In general the idea is correct I think - if you need to refresh the list of active processes every time. 总的来说,我认为这个想法是正确的-如果您每次都需要刷新活动进程列表。 So updating the list using timer is ok. 因此,使用计时器更新列表是可以的。 I don't know Win32 API very well, but I think it would be a security issue if anybody could subscribe to process_run and process_retminate wineows events, so it is unlikely to be possible. 我不太了解Win32 API,但我认为如果任何人都可以订阅process_run和process_retminate wineows事件将是一个安全问题,因此这不太可能。

But do you really need to update it all the time? 但是,您真的需要一直对其进行更新吗? Maybe it woule be enough to read process list only when combobox expands? 也许仅在combobox展开时足以读取进程列表了吗? When user will expand it next time, you will reinit items again. 当用户下次扩展它时,您将再次重新初始化项目。 I think this approach will cause less problems. 我认为这种方法将减少问题。

As fo your implementation, I think it is not the most effifient and elegant: 对于您的实现,我认为这不是最高效,最优雅的:

  1. Storing the whole Process object in the combobox item is not good as for me. 对我来说,将整个Process对象存储在组合框项中并不好。 Better create your class, that will store only those properties you need (Process ID, Process Name) 更好地创建您的类,该类将仅存储您需要的那些属性(流程ID,流程名称)
  2. using current.Count() in a loop is extreemely inefficient - it is extention method that always iterates on IEnumerable on call. 在循环中使用current.Count()效率极低-它是扩展方法,始终在调用时在IEnumerable上进行迭代。 So your 所以你

    for (byte Índex = 0; Índex < current.Count(); Índex++) for(字节Índex= 0;Índex<current.Count();Índex++)

    results in O(N*N) complexity. 导致O(N * N)复杂度。 Fortunately process count will be not too big to affect your application very much, but you should know this fact and do not get used to using this method in a loop. 幸运的是,进程数不会太大,不会对您的应用程序产生太大影响,但是您应该知道这一事实,并且不要习惯于在循环中使用此方法。 use current.Length instead as it is an array. 使用current.Length代替,因为它是一个数组。

  3. Your collection synchronization is too complex and strange. 您的集合同步过于复杂和奇怪。 Why not to make a method that receives collection to change and collection to init from and makes first collection to be equal to second using add-remove operations? 为什么不使用add-remove操作创建一个方法来接收要更改的集合和要初始化的集合,并使第一个集合等于第二个集合呢? Of you will have both collections sorted by some property (Process name for example), this can be done very simple and efficient - using binary search . 你们当中的两个集合都将按某种属性(例如,流程名称)进行排序,这可以非常简单和高效地完成-使用二进制搜索 In WPF you can use ObservableCollection as dataSource to use this approach most effectively. 在WPF中,可以将ObservableCollection用作数据源,以最有效地使用此方法。 In WinForms you probably can also use collections with change notification, but I haven't used them. 在WinForms中,您可能还可以将集合与更改通知一起使用,但是我没有使用它们。

You can do it even more simple: 您可以做得更简单:

//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();

But this approach will always reinit all items if combobox and some blinking is possible. 但是,如果组合框出现闪烁,此方法将始终重新初始化所有项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM