我必须做一些完全错误的事情,但我无法弄清楚。我有一个表单,我在VS中添加了一个计时器控件。我还有一个正在监视应用程序启动的类(notepad.exe)。当事件到达时,它应该启用计时器,设置间隔并在每个刻度上执行某些操作(例如触发消息框或更改标签)。这似乎没有发生。看看代码可以帮助别人给我一些线索。代码如下:
public partial class Monitor : Form
{
EventWatcher eventWatch = new EventWatcher();
ManagementEventWatcher startWatcher = new ManagementEventWatcher();
ManagementEventWatcher endWatcher = new ManagementEventWatcher();
public Monitor()
{
InitializeComponent();
startWatcher = eventWatch.WatchForProcessStart("notepad.exe");
endWatcher = eventWatch.WatchForProcessEnd("notepad.exe");
}
private void appTimer_Tick(object sender, EventArgs e)
{
label1.Text = "tick";
MessageBox.Show("Tick");
}
}
守望者班是
class EventWatcher
{
public ManagementEventWatcher WatchForProcessStart(string processName)
{
string queryString =
"SELECT TargetInstance" +
" FROM __InstanceCreationEvent " +
"WITHIN 2 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + processName + "'";
// The dot in the scope means use the current machine
string scope = @"\\.\root\CIMV2";
// Create a watcher and listen for events
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
watcher.EventArrived += ProcessStarted;
watcher.Start();
return watcher;
}
public void ProcessStarted(object sender, EventArrivedEventArgs e)
{
Monitor monitor = new Monitor();
//set timer interval and start time for Monitor class. (form)
monitor.appTimer.Interval = 5000;
monitor.appTimer.Enabled = true;
MessageBox.Show("notepad started");
}
}
我注意到两件事:
当notepad.exe启动并且MessageBox.Show("notpad started");
行注释掉时,计时器刻度事件中的messabox将不会触发。如果它如上所示,它将显示两个消息框(记事本开始和勾选)。但是,label1.Text
无论如何都不会改变。
我不确定我做错了什么。我确信它与如何处理计时器事件有关,但我不确定我应该做什么。有什么想法吗?
答案 0 :(得分:2)
您的代码会创建一个新的Monitor实例。 因此,您不会访问名为eventWatch.WaitForProcessStart()的Monitor实例的属性,因此它们不会更改。 解决此问题的一种方法是在触发ProcessStarted()时触发事件。 您的代码可能如下所示:
class EventWatcher
{
public event EventHandler<EventArrivedEventArgs> ProcessStarted;
public ManagementEventWatcher WatchForProcessStart(string processName)
{
string queryString =
"SELECT TargetInstance" +
" FROM __InstanceCreationEvent " +
"WITHIN 2 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + processName + "'";
// The dot in the scope means use the current machine
string scope = @"\\.\root\CIMV2";
// Create a watcher and listen for events
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
watcher.EventArrived += OnProcessStarted;
watcher.Start();
return watcher;
}
protected virtual void OnProcessStarted(object sender, EventArrivedEventArgs e)
{
EventHandler<EventArrivedEventArgs> copy = ProcessStarted;
if (copy != null)
copy(sender, e); // fire the event
}
}
public partial class Monitor : Form
{
EventWatcher eventWatch = new EventWatcher();
ManagementEventWatcher startWatcher = new ManagementEventWatcher();
ManagementEventWatcher endWatcher = new ManagementEventWatcher();
public Monitor()
{
InitializeComponent();
startWatcher = eventWatch.WatchForProcessStart("notepad.exe");
startWatcher.ProcessStarted += startWatcher_ProcessStarted; // subscribe to the event
endWatcher = eventWatch.WatchForProcessEnd("notepad.exe");
}
private void startWatcher_ProcessStarted(object sender, EventArrivedEventArgs e)
{
Monitor monitor = new Monitor();
//set timer interval and start time for Monitor class. (form)
monitor.appTimer.Interval = 5000;
monitor.appTimer.Enabled = true;
MessageBox.Show("notepad started");
}
private void appTimer_Tick(object sender, EventArgs e)
{
label1.Text = "tick";
MessageBox.Show("Tick");
}
}
答案 1 :(得分:0)
当您从另一个线程运行时,label1.Text
看起来也不会改变。您需要在该标签上运行调用以从ManagementEventWatcher
更新它。
使用此课程:
using System;
using System.Windows.Forms;
public static class ControlExtensions
{
/// <summary>
/// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
/// </summary>
/// <param name="control"></param>
/// <param name="code"></param>
public static void UIThread(this Control @this, Action code)
{
if (@this.InvokeRequired)
{
@this.BeginInvoke(code);
}
else
{
code.Invoke();
}
}
}
and replace `label1.Text = "tick" ` with
this.UIThread(() => this.label1.Text = "tick"));