簡體   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