2012-03-22 1 views
2

私は、USB経由で接続されたデバイスからいくつかの値をサンプリングするはずの小さなプログラムを持っています。 私は、デバイスごとに0.5秒をサンプリングしたい - 私は、それ自体ごと500milisecondsを繰り返しループを作成し、かなりうまく機能:C#でInifinite Loopを処理する方法

while(_bool) 
{ 
    Sample_USB_Device(); 
    Present_Data_To_Screen(); 
} 

私の質問はこれです:

私は_bool変数を制御することができますどのように?コードを実行すると、GUIがフリーズし、アクセスできなくなります。私はスレッドを使用しようとしましたが、スレッドからGUIにデータを戻すことができません(または、私は方法を知らない)。

+2

だけで何 –

+0

LBはそれを持っている「バックグラウンドスレッドからGUIを更新する」ために、あなたはBackgroundWorkerのを必要とするhttp://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx – deltree

+0

を検索GUIフレームワークを使用していますか? WinForms、WPF、または何か他のもの? –

答えて

6

ループを使用する代わりに、Timerを使用して、指定した間隔でコードを実行できます。タイマーを有効または無効にすることができます。

+0

それはすごいです、私は彼が何らかの理由ですでにタイマーを使っていたと思っていました。 – ashes999

+0

Sample_USB_Device()がかなり速い場合、それは良い解決策です。そうでない場合、Sample_USB_DeviceはUIスレッド、すなわち実行中のUIブロックで実行されることに留意されたい。 – Heinzi

+0

Sample_USB_Device()は約(1/50)秒で結果を返さなければならないので、私は良いと思います... – Trout

0

使用のスレッド:

public class ThreadExample { 
    private bool _running; 
    public void start() { 
     Thread t = new Thread(doStuff); 
     _running = true; 
     t.Start(); 
    } 

    public void stop() { 
     _running = false; 
    } 

    public void doStuff() { 
     while(_running){ 
      Sample_USB_Device(); 
      Present_Data_To_Screen(); 
      Thread.Sleep(500); 
     } 
    } 
} 
+0

Present_Data_To_Screenは、おそらくバックグラウンドスレッドで実行されているため、UI要素を直接更新することはできません。 – Heinzi

0
  • あなたはポーリングのためのイベントを発生するためにタイマーを使用することができるかもしれないが、それは
  • を制限することができますが、別のスレッドで、あなたの投票を実行しますが、ことを覚えることができますあなたはそれを作成したスレッドを除いてguiを更新することはできません...使用gui安全な方法でアップデートを実行するには
  • あなたのループを継続するかどうかであなたの価値を行うためのスレッドセーフな方法は、Interlockedを使用することです。読んで連動しています。
0

ここでは、バックグラウンドを使用してください。

backgroundWorker1.RunWorkerAsync(); // Start the backgroundworker. 

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    // Do you stuff here. 
} 

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    // Report the changes. 
    // NOTE: backgroundWorker1.WorkerReportsProgress = true; has to be true. 
} 

private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
{ 
    // Do something when we are done. 
} 

編集:これは凍結の問題のみを停止します。

0

ループをバックグラウンドで実行するには、BackgroundWorkerを使用します。これはあなたのUIが応答とどまることを保証します:

TPLは、あなたが戻って結果をデバイスをポーリングし、自動的にマーシャリングされます定義された間隔で、非同期イベント・ハンドラを呼び出すことができますC#5.0 &と Timerを使用して
BackgroundWorker bw; 

public void StartBackgroundLoop() { 
    bw = new BackgroundWorker(); 
    bw.WorkerSupportsCancellation = true; 
    bw.WorkerReportsProgress = true; 

    bw.DoWork += (sender, e) => { 
     // this will happen in a background thread 
     while (!bw.CancellationPending) { 
      data = Sample_USB_Device(); 
      bw.ReportProgress(0, data); 
     } 
    } 

    // this event is triggered *in the UI thread* by bw.ReportProgress 
    bw.ProgressChanged += (sender, e) => { 
     Data data = (Data)e.UserState; // this is the object passed to ReportProgress 
     Present_Data_To_Screen(data); 
    } 

    bw.RunWorkerAsync(); // starts the background worker 
} 

public void StartBackgroundLoop() { 
    bw.CancelAsync();  // sets bw.CancellationPending to true 
} 
0

UIスレッドに追加します。

public partial class Form1 : Form 
{ 
    private readonly Timer _sampleTimer; 

    public Form1() 
    { 
     InitializeComponent(); 

     _sampleTimer = new Timer 
      { 
       Interval = 500 // 0.5 Seconds 
      }; 
     _sampleTimer.Tick += SampleUsb; 
    } 

    private async void SampleUsb(object sender, EventArgs e) 
    { 
     // Since we asynchronously wait, the UI thread is not blocked by "the work". 
     var result = await SampleUsbDeviceAsync(); 

     // Since we resume on the UI context, we can directly access UI elements. 
     resultTextField.Text = result; 
    } 

    private async Task<string> SampleUsbDeviceAsync() 
    { 
     await Task.Delay(1000); // Do actual work sampling usb async (not blocking ui) 
     return DateTime.Now.Ticks.ToString(); // Sample Result 
    } 

    private void startButton_Click(object sender, EventArgs e) 
    { 
     _sampleTimer.Start(); 
    } 

    private void stopButton_Click(object sender, EventArgs e) 
    { 
     _sampleTimer.Stop(); 
    } 
関連する問題