C# 如何在C语言中处理有限循环#
我有一个小程序,可以从通过USB连接的设备上采集一些值。 我想每0.5秒对设备进行一次采样-因此我创建了一个循环,每500毫秒重复一次,效果非常好: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(或者我不知道如何发送)。您可以使用以指定间隔运行代码,而不是使用循
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元素,因为它在后台线程中运行。