我正在尝试编写一个无需使用计时器即可继续执行方法的程序。例如,我想要一个显示当前正在运行的进程列表的程序。显然,它在不断变化。我不想使用每秒获取进程列表并将它们添加到列表中的计时器,因为它对我来说看起来不是很优雅。有什么特别的方法可以做到这一点吗?我怎样才能提供可以实现这一目标的服务?
5 回答
就个人而言,我会为此坚持使用计时器。它真的很优雅。但是,如果你真的想要一些更有活力的东西,那么请继续阅读!
随着新关键字async
和await
关键字(将包含在 C# 5.0 中)的流行,我们可能会看到计时器变得越来越不酷1。这是您现在使用Async CTP在没有计时器的情况下如何做到这一点的方法。
private async void ShowProcessesButton_Click(object sender, EventArgs args)
{
while (true)
{
await Task.Delay(1000); // TaskEx.Delay in the CTP
YourListBox.Items.Clear();
foreach (Process p in Process.GetProcesses())
{
YourListBox.Items.Add(p.ProcessName);
}
}
}
很奇怪吧?它可能不是如何async
以及应该如何await
使用的理想示例,但您明白了。这是未来的浪潮。
1不要误会我的意思。总是需要传统的计时器类。
您可以使用无限循环(直到进程退出)生成较低优先级的线程,以定期更新您的进程列表。如果没有关于您正在使用哪种控件的更多信息,或者我无法真正帮助您使用 Control 更新委托,但您的函数的粗略骨架将是:
private void processUpdater()
{
while (true) //not the most elegant way to implement a pseudo-infinite loop, but you can figure out how you want to signal it to end.
{
var runningProcesses = Process.GetProcesses().Where(p => !string.IsNullOrEmpty(p.MainWindowTitle)).Select(p => p.MainWindowTitle); //filter the running processes to get those with open windows.
this.lstProcesses.Invoke((MethodInvoker)delegate { this.lstProcesses.Items.Clear(); }); //thread-safe invocation to clear the current items
this.lstProcesses.Invoke((MethodInvoker)delegate { this.lstProcesses.Items.AddRange(runningProcesses.ToArray<string>()); }); //add the new set of windowed processes
System.Threading.Thread.Sleep(5000); //update the list every 5 seconds
}
}
在我的情况下,我只是使用窗口捕获进程,并在列表框中列出这些窗口标题(lstProcesses)
现在,产生这个线程:
var tUpdater = new System.Threading.Thread(processUpdater);
tUpdater.Priority = System.Threading.ThreadPriority.BelowNormal;
tUpdater.Name = "Process List Updater";
tUpdater.Start(); //start the thread running.
显然这是一个非常基本的实现,但希望它能让你大致了解如何做你想做的事。
如果您不使用计时器,您将需要执行以下操作:
- 在您的应用启动时获取列表或正在运行的进程
- 检测进程何时启动并将其添加到列表中
- 检测进程何时结束并将其从列表中删除
要检测进程创建/终止,请查看此答案:
程序1:
您可以开发一个持续运行的 Windows 服务。不需要计时器。如果您能给我们提供更多细节,我们可以提出更好的解决方案。但请记住,窗口服务不可能进行用户交互。
正在运行的进程被添加到 observablecollection 中。每当添加一个项目时,它都会引发 CollectionChanged 事件。
程序2:
您可以有一个程序,您希望将正在运行的进程列表公开为 Web 服务,该 Web 服务在 Program1 中使用。在program1的CollectionChanged事件处理程序中,您可以调用program2的webservice并通知新添加的进程。
我不同意认为 Timers 是这里唯一或最佳答案的评论。当变化发生时希望得到警报,而不是轮询它,这是一种崇高的追求。我相信您正在寻找一个 WinAPI “Hook”,但我不知道是哪一个或它是否存在。
请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/ms644959%28v=vs.85%29.aspx