C# 如何在C语言中处理有限循环#

C# 如何在C语言中处理有限循环#,c#,infinite-loop,C#,Infinite Loop,我有一个小程序,可以从通过USB连接的设备上采集一些值。 我想每0.5秒对设备进行一次采样-因此我创建了一个循环,每500毫秒重复一次,效果非常好: while(_bool) { Sample_USB_Device(); Present_Data_To_Screen(); } 我的问题是: 如何控制\u bool变量?当我运行代码时,GUI冻结,我没有任何访问权限。我尝试使用线程,但无法将数据从线程发送回GUI(或者我不知道如何发送)。您可以使用以指定间隔运行代码,而不是使用循

我有一个小程序,可以从通过USB连接的设备上采集一些值。 我想每0.5秒对设备进行一次采样-因此我创建了一个循环,每500毫秒重复一次,效果非常好:

while(_bool)
{
    Sample_USB_Device();
    Present_Data_To_Screen();
}
我的问题是:

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

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

使用线程:

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);
        } 
    }
}
  • 您可以使用计时器触发事件进行轮询,但这可能会造成限制
  • 您可以在另一个线程中运行轮询,但请记住,除了在创建gui的线程上,您无法更新gui。。。使用Invoke以gui安全的方式进行更新
  • 对是否继续循环进行评估的线程安全方法是使用interlocted.Read和interlocted.Increment方法

    • 在这里,使用背景

      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.
      }
      
      编辑:这只会停止冻结问题。

      使用在后台执行循环。这将确保您的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
      }
      
      使用with 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();
          }
      
      公共部分类表单1:表单
      {
      专用只读定时器_sampleTimer;
      公共表格1()
      {
      初始化组件();
      _sampleTimer=新计时器
      {
      间隔=500//0.5秒
      };
      _sampleTimer.Tick+=SampleUsb;
      }
      专用异步void SampleUsb(对象发送方,事件参数e)
      {
      //由于我们异步等待,UI线程不会被“工作”阻塞。
      var result=await SampleUsbDeviceAsync();
      //因为我们在UI上下文上继续,所以我们可以直接访问UI元素。
      resultTextField.Text=结果;
      }
      专用异步任务SampleUsbDeviceAsync()
      {
      等待任务。延迟(1000);//进行实际工作采样usb异步(不阻塞ui)
      return DateTime.Now.Ticks.ToString();//示例结果
      }
      私有无效开始按钮单击(对象发送者,事件参数e)
      {
      _sampleTimer.Start();
      }
      私有无效停止按钮\u单击(对象发送者,事件参数e)
      {
      _sampleTimer.Stop();
      }
      
      只需搜索“从后台线程更新gui”LB有了它,你需要一个后台工作人员你在使用什么GUI框架?WinForms、WPF或其他什么?提示:
      \u bool
      对于变量来说是一个非常糟糕的名字。最好根据数据表示的内容来命名变量,而不是根据数据的表示方式来命名。例如,称它为
      continuesSampling
      。\u bool只是一个例子,它不是实际的代码,但感谢您的建议。感谢所有的快速响应!太棒了,我以为他出于某种原因已经在使用计时器。如果Sample_USB_Device()非常快,这是一个很好的解决方案。如果不是,请注意Sample_USB_Device是在UI线程中执行的,也就是说,UI在执行期间会阻塞。Sample_USB_Device()应该在大约(1/50)秒后返回一个结果,所以我认为我很好…@Heinzi:如果使用同步读取,那么它将被阻止。如果使用带超时的异步读取,那么它不需要阻止UI线程。Present_Data_to_Screen可能无法直接更新UI元素,因为它在后台线程中运行。