如何将booleon从Worker_ProgressChanged传递回Worker_DoWork [英] How to pass booleon back from Worker_ProgressChanged to Worker_DoWork
问题描述
我正在使用后台工作程序读取值,并将值传递给Worker_ProgressChanged,以更新UI.
I'm using a Background worker to read values in and to pass values to Worker_ProgressChanged, to update UI.
在Worker_DoWork中:
In Worker_DoWork:
while (agi.DvmReadyToRead) // wait for digipot to be adjusted before reading in worker
{
Thread.Sleep(20);
Application.DoEvents();
//logS.Debug("Waiting for ready to read in worker");
}
Thread.Sleep(40); // Give digipot chance to make the change
agi.SendSoftwareTriggerOne();
Thread.Sleep(7); // Duration for above command to execute
A = agi.ReadOne();
Thread.Sleep(1);
agi.InitOne();
Thread.Sleep(1);
sAndH3 = A[0];
worker.ReportProgress(0, new System.Tuple<double>(sAndH3));
agi.DvmReadyToRead = true;
在Worker_ProgressChanged中:
In Worker_ProgressChanged:
while (!agi.DvmReadyToRead)
{
//logS.Debug("waiting for ready to read in progress");
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Thread.Sleep(0);
Application.DoEvents(); // Exception thown here
Thread.Sleep(1); // wait for DVM reading
}
agi.DvmReadyToRead = false;
// Then goes on to adjust output voltage up or down
第一次使用
Application.DoEvents();
但是,第一次运行后,此时我得到了stackoverflow.在这里阅读了许多文章之后,DoEvents并不是实现我想要实现的最佳方法. 因此,我想要的是将布尔值传递回DoWork的方法,或者是允许工作人员能够读取agi.DvmReadyToRead布尔值的另一种方法.
however after first run, I get a stackoverflow at this point. After reading many posts on here DoEvents is not the best way of doing what I am trying to achieve. So what I would like is a way to pass a Boolean back to DoWork, or another way to allow worker to be able to read the agi.DvmReadyToRead Boolean.
谢谢!
推荐答案
如果我理解您的问题,则说明您在测试和测量"中描述了一种非常常见的模式,其中有一种仪器在触发之前需要花费一些时间才能获得读.但是您想知道何时发生读取,以便您可以采取一些措施(例如更新ProgressBar或TextBox),并且希望能够取消工作程序循环.
If I understand your question, you are describing a very common pattern in Test and Measurement where you have an instrument that takes some time after triggering it before it gets a reading. But you want to know when the reading happens so that you can take some action (like update a ProgressBar or TextBox perhaps) and you want be able to cancel the worker loop.
当我需要自己执行此操作时,我喜欢使用System.Threading.Tasks进行简化.我将在此处发布一个完整的模式,希望您能找到一些有用的方法来解决您遇到的问题.
When I need to do this myself, I like to use the System.Threading.Tasks to simplify things. I'll post a complete pattern here in the hope that you can find something of use to solve the issue you are having.
为了清楚起见,我试图回答您的将布尔值传递回DoWork的方法..."的问题,方法是说从该方法中触发一个可能包含布尔值的Event_DoWork事件(例如您询问)或加倍(在我的示例中)或您选择的其他任何信息.
To be clear, I am trying to answer your question of "a way to pass a Boolean back to DoWork..." by saying that one way to do this is to fire an Event from Worker_DoWork that can contain Boolean (like you asked) or double (in my example) or any other information you choose.
祝你好运!
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StackOverflow02
{
public partial class DVMLoopRunner : Form
{
public DVMLoopRunner()
{
InitializeComponent();
DVMReadingAvailable += Form1_DVMReadingAvailable;
ContinueOrCancel += Form1_ContinueOrCancel;
}
// See if User has turned off the Run button then cancel worker
private void Form1_ContinueOrCancel(Object sender, CancelEventArgs e)
{
e.Cancel = !checkBoxRunMeterLoop.Checked;
}
// The DVM, after being triggered + some delay, has come up with a new reading.
private void Form1_DVMReadingAvailable(Object sender, DVMReadingAvailableEventArgs e)
{
// To update GUI from worker thread requires Invoke to prevent Cross-Thread Exception
Invoke((MethodInvoker)delegate
{
textBox1.Text = e.Reading.ToString("F4");
});
}
// Make our events so that we can be notified of things that occur
public event CancelEventHandler ContinueOrCancel;
public event DVMReadingAvailableEventHandler DVMReadingAvailable;
// This is how we will provide info to the GUI about the new reading
public delegate void DVMReadingAvailableEventHandler(Object sender, DVMReadingAvailableEventArgs e);
public class DVMReadingAvailableEventArgs : EventArgs
{
public readonly double Reading;
public DVMReadingAvailableEventArgs(double reading)
{
Reading = reading;
}
}
// When the User checks the box, Run the worker loop
private void checkBoxRunMeterLoop_CheckedChanged(Object sender, EventArgs e)
{
if(checkBoxRunMeterLoop.Checked)
{
Task.Run(() => ReadDVMWorker());
}
}
// Worker Loop
private void ReadDVMWorker()
{
while(true)
{
CancelEventArgs e = new CancelEventArgs();
ContinueOrCancel?.Invoke(this, e);
if (e.Cancel) return; // If User has turned off the Run button then stop worker
ReadDVM(); // This worker thread will block on this. So trigger, wait, etc.
}
}
// DVM Takes some period of time after trigger
void ReadDVM()
{
Thread.Sleep(1000);
double newSimulatedReading = 4.5 + Random.NextDouble();
DVMReadingAvailable?.Invoke(this, new DVMReadingAvailableEventArgs(newSimulatedReading));
}
Random Random = new Random(); // Generate random readings for simulation
}
}
这篇关于如何将booleon从Worker_ProgressChanged传递回Worker_DoWork的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!