2012-02-05 3 views
0

何かを完全に間違っているに違いないが、私はそれを理解できない。私はフォームを持っており、VSにタイマーコントロールを追加します。私はまた、アプリケーションが起動するのを見ているクラスを持っています(notepad.exe)。イベントが到着すると、タイマーを有効にし、間隔を設定し、各ティックで何かを実行します(メッセージボックスの起動やラベルの変更など)。これは起こっていないようです。コードの一見は、誰かが私に手がかりを与えるのを助ける。以下のコードは次のとおりです。私は2つのことに気づいた別のクラスのタイマーを有効にした後にタイマーティックイベントを呼び出す

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は何に関係なく変更されません。

私が間違っていることはわかりません。私はタイマーイベントの処理方法と関係があると確信していますが、何をすべきか分かりません。何か案は?

答えて

2

このコードでは、Monitorの新しいインスタンスが作成されます。 したがって、eventWatch.WaitForProcessStart()で呼び出されたMonitorのインスタンスのプロパティにアクセスしていないため、変更されません。 これを解決する1つの方法は、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"); 
    } 

} 
+0

おかげで、違っいずれかを動作するようには思えません。 "notepad started"を示すmessaboxが存在しない場合、他のmessageboxはティッカーで起動しません。ラベルはどちらの方法でも変わらず、私は今ではクロススレッドエラーが発生します。私は新しい事例であなたが言ったことを疑っていました。タイマーを静的フィールドにしてもこの問題を解決できないでしょうか?しかし、それはしません。 –

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")); 
+0

これは、label1が私の古いコードで変わるという意味で、よりうまくいくようです。しかし、これは、ProcessStarted関数にメッセージボックスがある場合にのみ発生します。 –

関連する問題