2

タイマーを使用しないことにしました。私がしたことはもっと簡単です。

バックグラウンドワーカーを追加しました。Shownイベントを追加しました。Shownイベントは、すべてのコンストラクターがロードされた後に発生します。Shownイベントでは、backgroundworker非同期を開始しています。

バックグラウンドワーカーのDoWorkで、次のことを行っています。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while(true)
            {
                cpuView();
                gpuView();
                Thread.Sleep(1000);
            }
        }
4

6 に答える 6

9

この場合、2つを使用System.Threading.Timerし、これら2つのスレッドでCPUを集中的に使用する操作を実行することをお勧めします。を使用してコントロールにアクセスする必要があることに注意してくださいBeginInvoke。これらのアクセスをプロパティセッターにカプセル化することも、ビューモデルクラスに引き出すこともできます。

public class MyForm : Form
{
    private System.Threading.Timer gpuUpdateTimer;
    private System.Threading.Timer cpuUpdateTimer;

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        if (!DesignMode)
        {
            gpuUpdateTimer = new System.Threading.Timer(UpdateGpuView, null, 0, 1000);
            cpuUpdateTimer = new System.Threading.Timer(UpdateCpuView, null, 0, 100);
        }
    }

    private string GpuText
    {
        set
        {
            if (InvokeRequired)
            {
                BeginInvoke(new Action(() => gpuLabel.Text = value), null);
            }
        }
    }

    private string TemperatureLabel
    {
        set
        {
            if (InvokeRequired)
            {
                BeginInvoke(new Action(() => temperatureLabel.Text = value), null);
            }
        }
    }

    private void UpdateCpuView(object state)
    {
        // do your stuff here
        // 
        // do not access control directly, use BeginInvoke!
        TemperatureLabel = sensor.Value.ToString() + "c" // whatever
    }

    private void UpdateGpuView(object state)
    {
        // do your stuff here
        // 
        // do not access control directly, use BeginInvoke!
        GpuText = sensor.Value.ToString() + "c";  // whatever
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (cpuTimer != null)
            {
                cpuTimer.Dispose();
            }
            if (gpuTimer != null)
            {
                gpuTimer.Dispose();
            }
        }

        base.Dispose(disposing);
    }
于 2012-08-04T19:46:28.693 に答える
3

このコードをバックグラウンドワーカーにスローして、機能することを期待することはできません。UI要素(ラベル、テキストボックスなど)を更新するものはすべて、メインスレッドで呼び出す必要があります。データを取得するためのロジックと、UIを更新するためのロジックを分割する必要があります。

私はあなたの最善の策はこれを行うことだと思います:

タイマーTick()メソッドの場合:

// Disable the timer.
// Start the background worker

バックグラウンドワーカーのDoWork()メソッド:

// Call your functions, taking out any code that 
// updates UI elements and storing this information 
// somewhere you can access it once the thread is done.

バックグラウンドワーカーのCompleted()メソッド:

// Update the UI elements based on your results from the worker thread
// Re-enable the timer.
于 2012-08-04T19:38:31.943 に答える
3

まず、マルチスリーシングに頭を悩ませることを忘れないでください。それは問題です(特にUIのもの)。

次に、次のような何かを使用できます

public class Program
{
    public static void Main(string[] args)
    {
        Timer myTimer = new Timer(TimerTick, // the callback function
            new object(), // some parameter to pass
            0, // the time to wait before the timer starts it's first tick
            1000); // the tick intervall
    }

    private static void TimerTick(object state)
    {
        // less then .NET 4.0
        Thread newThread = new Thread(CallTheBackgroundFunctions);
        newThread.Start();

        // .NET 4.0 or higher
        Task.Factory.StartNew(CallTheBackgroundFunctions);
    }

    private static void CallTheBackgroundFunctions()
    {
        cpuView();
        gpuView();
    }
}

( John Koernerが言ったように)あなたのことを覚えておいてください。そのままでは機能cpuView()gpuView()ません。

于 2012-08-04T19:45:15.653 に答える
2

はい、できます:

タイマーティックイベントの場合:

private void timer_Tick(object sender, EventArgs e)
{

  timer.Enabled = false;

  backgroundworker.RunWorkerAsync();

  timer.Enabled = true;
}

あなたのBackgroundworkerdoworkイベントで:

private void backgroundworker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
   try
   {
       //Write what you want to do
   }
   catch (Exception ex)
   {
       MessageBox.Show("Error:\n\n" + ex.Message, "System", MessageBoxButtons.OK, MessageBoxIcon.Error);
   }
}
于 2016-05-23T22:05:40.390 に答える
1

BackgroundWorkerこの場合、複雑すぎると思います。保証付きのTimer停止を実装することは困難です。

必要な間隔でThreadキャンセルを待機するループでworkerを使用することをお勧めします。ManualResetEvent

  • キャンセルイベントが設定されている場合、ワーカーはループを終了します。
  • タイムアウト(必要な時間間隔を超える)がある場合は、システム監視を実行します。

これがコードのドラフトバージョンです。私はそれをテストしていませんが、それはあなたにアイデアを示すことができることに注意してください。

public class HardwareMonitor
{
    private readonly object _locker = new object();
    private readonly TimeSpan _monitoringInterval;
    private readonly Thread _thread;
    private readonly ManualResetEvent _stoppingEvent = new ManualResetEvent(false);
    private readonly ManualResetEvent _stoppedEvent = new ManualResetEvent(false);

    public HardwareMonitor(TimeSpan monitoringInterval)
    {
        _monitoringInterval = monitoringInterval;
        _thread = new Thread(ThreadFunc)
            {
                IsBackground = true
            };
    }

    public void Start()
    {
        lock (_locker)
        {
            if (!_stoppedEvent.WaitOne(0))
                throw new InvalidOperationException("Already running");

            _stoppingEvent.Reset();
            _stoppedEvent.Reset();
            _thread.Start();
        }
    }

    public void Stop()
    {
        lock (_locker)
        {
            _stoppingEvent.Set();
        }
        _stoppedEvent.WaitOne();
    }

    private void ThreadFunc()
    {
        try
        {
            while (true)
            {
                // Wait for time interval or cancellation event.
                if (_stoppingEvent.WaitOne(_monitoringInterval))
                    break;

                // Monitoring...
                // NOTE: update UI elements using Invoke()/BeginInvoke() if required.
            }
        }
        finally
        {
            _stoppedEvent.Set();
        }
    }
}
于 2012-08-04T21:02:11.490 に答える
1

私の場合、WinFormアプリケーションでBackgroundWorkerSystem.Timers.Timer、およびProgressBarを使用していました。私が遭遇したのは、BackgroundWorkerのDo-Workを繰り返すという2番目のティックです。BackgroundWorkerのProgressChangedでProgressBarを更新しようとすると、クロススレッド例外が発生します。その後、SO @Rudedog2https : //stackoverflow.comで解決策を見つけました。 / a / 4072298/1218551は、Windowsフォームで使用するためにTimers.Timerオブジェクトを初期化するときに、タイマーインスタンスのSynchronizingObjectプロパティをフォームに設定する必要があることを示しています。

systemTimersTimerInstance.SynchronizingObject = this; // this = form instance.

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

于 2018-01-30T10:27:45.180 に答える