使用线程持续检查值的更改
本文关键字:检查 线程 | 更新日期: 2023-09-27 18:31:23
我正在尝试创建一个线程,该线程将持续检查值的更改,然后在位于我的GUI中的PictureBox中直观地显示该更改。
我实际写的东西有点复杂,所以我在保留基本思想的同时简化了它,如果这还不够,我很乐意提供澄清:
public class CheckPictures
{
PictureBox update;
List<String> check;
public CheckPictures(PictureBox anUpdate, List<String> aCheck)
{
update = anUpdate;
check = aCheck;
}
public void start()
{
while(true)
{
if (aCheck[0] == "Me")
{
update.Image = Image.fromFile("");
}
}
}
}
static int Main(string[] args)
{
List<String> picturesList = new List<String>();
CheckPictures thread1 = new CheckPictures(PictureBox1, picturesList);
Thread oThread1 = new Thread(thread1.start));
}
我希望它做的是动态更改 PictureBox1 中的图片,如果我要将字符串"我"添加到 pictureList。上面的代码不像我希望的那样工作。我曾认为通过传递实际的 PictureBox 和列表,对其他地方的列表的任何更改都会被线程捕获。所以我的第一个问题是:这可能吗?如果是这样,我需要对我的代码进行什么更改才能实现它?
您可能希望使用事件。您注册一个事件处理程序,当一个线程中的某些内容发生更改时,它会调用另一个线程中的事件处理程序来完成工作。忙于等待浪费 CPU。
你肯定不想做无限循环,这只会消耗 CPU:
while(true)
{
if (aCheck[0] == "Me")
{
update.Image = Image.fromFile("");
}
}
我认为你应该看看CountdownLatch类。
public class CountdownLatch
{
private int m_remain;
private EventWaitHandle m_event;
public CountdownLatch(int count)
{
m_remain = count;
m_event = new ManualResetEvent(false);
}
public void Signal()
{
// The last thread to signal also sets the event.
if (Interlocked.Decrement(ref m_remain) == 0)
m_event.Set();
}
public void Wait()
{
m_event.WaitOne();
}
}
这里的基本思想是,您需要在线程上停止执行一段时间,并在满足特定条件(可能在另一个线程上)时恢复。
换句话说,您将拥有一个计数器,在特定条件下递减其值,每当它变为零时,您就会触发事件,执行一些代码,然后重新开始(停止执行并等待计数器变为零)。
在您的情况下,您可以将计数器设置为 1,并在设置aCheck[0] = "Me";
时递减其值 这样您就不会浪费 CPU。
伪代码:
初始化计数器:
CountdownLatch latch = new CountdownLatch(1);
使线程等待:
public void start()
{
while(true)
{
latch.Wait(); //execution stops
{
//execution resumes once the latch counter is zero.
if (aCheck[0] == "Me") //double check you have what you need
{
update.Image = Image.fromFile("");
latch = new CountdownLatch(1); //reset if you need to do it again
}
}
}
}
只要满足您的条件(即 aCheck[0] = "Me";
) 向闩锁发出信号:
latch.Signal();
最后一行将使线程恢复执行。好东西。
创建一些对象,当添加新图片时,该对象将引发事件。 例如.class代表图片集:
public class PicturesCollection
{
public event EventHandler<PictureAddedEventArgs> PictureAdded;
private List<string> _pictures = new List<string>();
public void Add(string name)
{
_pictures.Add(name);
if (PictureAdded != null)
PictureAdded(this, new PictureAddedEventArgs(name));
}
public IEnumerable<string> Pictures
{
get { return _pictures; }
}
}
如果要向事件提供一些其他数据,请创建自定义事件参数:
public class PictureAddedEventArgs : EventArgs
{
public PictureAddedEventArgs(string name)
{
Name = name;
}
public string Name { get; private set; }
}
您现在需要的 - 创建图片集并订阅该活动:
static int Main(string[] args)
{
PicturesCollection pictures = new PicturesCollection();
pictures.PictureAdded += Pictures_PictureAdded;
}
static void Pictures_PictureAdded(object sender, PictureAddedEventArgs e)
{
if (e.Name == "Me")
PictureBox1.Image = Image.fromFile("");
}
如果在应用程序中的某个位置将新图片添加到集合中,它将引发 PictureAdd 事件,您可以处理和更新 PictureBox。在这种情况下,不会浪费 CPU。