如何在C#中处理无限循环

时间:2012-03-22 15:51:13

标签: c# infinite-loop

我有一个小程序,它应该从通过USB连接的设备中取样一些值。 我想每隔0.5秒对设备进行一次采样 - 所以我创建了一个每500毫秒重复一次的循环并且运行良好:

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

我的问题是:

如何控制_bool变量?当我运行代码时,GUI冻结,我没有任何访问权限。我试图使用Threads,但是我无法将数据从线程发送回GUI(或者我不知道如何)。

6 个答案:

答案 0 :(得分:7)

您可以使用Timer以指定的时间间隔运行代码,而不是使用循环。可以启用或禁用计时器。

答案 1 :(得分: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);
        } 
    }
}

答案 2 :(得分:0)

  • 您可以使用计时器触发事件​​进行轮询,但这可能会限制
  • 您可以在另一个线程中运行您的轮询,但请记住,除了创建它的线程之外,您无法更新gui ...使用Invoke以安全的方式进行更新
  • 一种线程安全的方法来判断是否继续循环是使用Interlocked.Read和Interlocked.Increment方法。

答案 3 :(得分: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.
}

编辑:这只会阻止您的冻结问题。

答案 4 :(得分:0)

使用BackgroundWorker在后台执行循环。这将确保您的UI保持响应:

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
}

答案 5 :(得分: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();
    }