2012-03-22 66 views
2

我有一個是應該品嚐來自通過USB連接的設備一定價值的小程序。 我想品嚐每0.5秒設備 - 所以我創建了一個循環,重複自己每500miliseconds和工作得很好:如何處理Inifinite循環在C#

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

我的問題是這樣的:

我怎樣才能控制_bool變量?當我運行代碼時,GUI凍結,我無法訪問它。我嘗試使用線程,但我無法將數據從線程發送回GUI(或者我不知道如何)。

+2

只要搜索「從後臺線程更新桂」 – 2012-03-22 15:52:47

+0

LB擁有它,你需要一個BackgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx – deltree 2012-03-22 15:53:54

+0

什麼你使用的是GUI框架? WinForms,WPF還是其他? [從後臺線程結果更新的WinForms UI]的 – 2012-03-22 15:54:24

回答

6

可以使用Timer在指定的時間間隔運行,而不是使用循環代碼。定時器可以啓用或禁用。

+0

太棒了,我以爲他出於某種原因已經在使用計時器了。 – ashes999 2012-03-22 15:55:22

+0

如果Sample_USB_Device()速度很快,那麼這是一個很好的解決方案。如果不是,請注意Sample_USB_Device在UI線程中執行,即執行期間的UI塊。 – Heinzi 2012-03-22 16:18:21

+0

Sample_USB_Device()應該在大約(1/50)秒內返回一個結果,所以我認爲我很好...... – Trout 2012-03-22 16:20:31

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 2012-03-22 16:02:19

0
  • 您可以使用一個計時器,以火爲輪詢的事件,但可以限制
  • 你可以運行你的調查中另一個線程,但請記住,你不能只是創建它的線程上更新GUI ...使用調用做在GUI安全的方式
  • 更新是線程安全的方法做就是否繼續你的循環你的價值是使用互鎖。 Read和Interlocked.Increment方法。
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在後臺執行你的循環。這將確保你的用戶界面保持響應:

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

使用Timer用C#5.0 & TPL將讓你調用一個異步事件,其在定義的時間間隔,這將輪詢設備,並自動馬歇爾結果返回到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(); 
    }