繁体   English   中英

在另一个类中启用计时器后调用Timer Tick事件

[英]Calling Timer Tick event after enabling timer in another class

我必须做一些完全错误的事情,但我无法弄清楚。 我有一个表单,我在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"); line注释掉计时器tick事件中的messabox不会触发。 如果它如上所示,它将显示两个消息框(记事本开始和勾选)。 但是,无论如何, label1.Text都不会改变。

我不确定我做错了什么。 我确信它与如何处理计时器事件有关,但我不确定我应该做什么。 有任何想法吗?

您的代码创建了一个新的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");
    }

}

它看起来像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"));

暂无
暂无

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

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