[英]How can i make a thread “report back” to main thread?
Im making a app that monitors stuff on my computer, and i want to make it somewhat more difficult then just implementing a while loop. 我正在制作一个应用程序,监视我的计算机上的东西,我想让它更难以实现一个while循环。
So my question is how do i do it if i would like to fetch cpu load in a seperate thread, that updates a static variable in class 所以我的问题是如果我想在一个单独的线程中获取cpu加载,如何在类中更新静态变量,我该怎么做呢
namespace threads
{
class Program
{
static int cpuload = 0;
static void Main(string[] args)
{
while (true)
{
Thread th = new Thread(new ThreadStart(CheckCPULoad));
th.Start();
Thread.Sleep(1000); // sleep the main thread
th.Abort();
Console.WriteLine("load: {0}%", cpuload);
}
}
static void CheckCPULoad()
{
// things are updated every 3 secs, dummy data
Thread.Sleep(3000);
Random rnd = new Random();
cpuload++;// = rnd.Next(0, 100); // dummy data
}
}
}
As it is "load: 0%" is printed every time. 因为每次都打印“load:0%”。 what do i need to fix to make it show 我需要修复什么才能让它显示出来
load: 0%
load: 0%
load: 0%
? ?
thanks 谢谢
In order to "report back" to the main thread, the main thread has to be "listening". 为了“回报”主线程,主线程必须是“监听”。 Which means, still running in a while loop and checking some kind of a queue for new items that represent the reports. 这意味着,仍然在while循环中运行并检查某种类型的队列以查找代表报告的新项目。
What you basically need is a queue where the worker thread will put its reports, and the main thread will periodically check this queue for reports from the worker. 您基本上需要的是一个队列,其中工作线程将放置其报告,主线程将定期检查此队列以获取来自该工作者的报告。
You have two main approaches: 您有两种主要方法:
If your application is a UI application you automatically get the first approach, as this is how the UI works. 如果您的应用程序是UI应用程序,则会自动获得第一种方法,因为这是UI的工作方式。 To add "an item" you can use Control.BeginInvoke (in winforms) or Dispatcher.BeginInvoke (in wpf). 要添加“项目”,您可以使用Control.BeginInvoke(在winforms中)或Dispatcher.BeginInvoke(在wpf中)。
The code you're using there starts the CheckCPULoad thread, waits 1 second and then aborts it. 你在那里使用的代码启动CheckCPULoad线程,等待1秒然后中止它。 However, the first thing the CheckCPULoad thread does is to sleep for 3 seconds. 但是,CheckCPULoad线程做的第一件事就是睡3秒钟。 So you never actually reach the cpuload++
instruction. 所以你永远不会真正达到cpuload++
指令。 I suspect this would be closer to what you intended: 我怀疑这将更接近你的意图:
namespace threads
{
class Program
{
static int cpuload = 0;
static void Main(string[] args)
{
Thread th = new Thread(new ThreadStart(CheckCPULoad));
th.Start();
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("load: {0}%", cpuload);
}
th.Abort(); // Don't ever reach this line with while (true)
}
static void CheckCPULoad()
{
while (true)
{
Thread.Sleep(3000);
cpuload++;
}
}
}
}
Use a timer and events instead. 请改用计时器和事件。 This way you avoid your sleeping/busy waiting. 这样可以避免您的睡眠/忙碌等待。 Also consider using Interlocked.Increment as suggested if several threads can modify the static variable at the same time. 如果多个线程可以同时修改静态变量,也可以考虑使用Interlocked.Increment。
using System;
using System.Threading;
using System.Timers;
using Timer = System.Timers.Timer;
namespace CpuLoad
{
internal class Program
{
private static int cpuload;
private static readonly AutoResetEvent autoEvent = new AutoResetEvent(false);
private static void Main(string[] args)
{
var timer = new Timer(3000);
timer.Elapsed += CheckCPULoad;
timer.Start();
while (true)
{
autoEvent.WaitOne();
autoEvent.Reset();
Console.WriteLine(cpuload);
}
}
private static void CheckCPULoad(object sender, ElapsedEventArgs e)
{
cpuload++;
autoEvent.Set();
}
}
}
If i get you right, this should solve your purpose. 如果我找对你,这应该可以解决你的目的。 Notice the while loop inside the CheckCPULoad()
method. 注意CheckCPULoad()
方法中的while循环。
class Program
{
static int cpuload = 0;
static void Main(string[] args)
{
Thread th = new Thread(new ThreadStart(CheckCPULoad));
th.Start();
while (true)
{
Thread.Sleep(1000);
Console.WriteLine("load: {0}%", cpuload);
}
th.Abort(); // Don't ever reach this line with while (true)
}
static void CheckCPULoad()
{
while (true)
{
Thread.Sleep(3000);
cpuload++;
}
}
}
Instead of cpuload++
try using 而不是cpuload++
尝试使用
Interlocked.Increment(ref cpuload);
Check - http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx 检查 - http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
The thread sleeps for 3 secs. 线程休眠3秒。 You abort it after 1. Go figure :) 你在1之后中止它。去图:)
With callback you can do that 通过回调,您可以做到这一点
here is an exsample: 这是一个例子:
public class Example2
{
// Declaration - Take 1 parameter, return nothing
public delegate void LogHandler(string message);
// Instantiation - Create a function which takes delegate as one parameter
// Verify if it is null before you use it
public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler("Process() begin");
}
if (logHandler != null)
{
logHandler("Process() end");
}
}
}
public class Example2DelegateConsumer
{
// Create a method with the same signature as the delegate
static void Logger(string s)
{
Console.WriteLine(s);
}
public static void Main(string[] args)
{
Example2 ex2 = new Example2();
// Invocation in the client
Example2.LogHandler myLogger = new Example2.LogHandler(Logger);
ex2.Process(myLogger);
}
}
In addition to my original (plagiarised) answer below, this sort of situation where you're observing a set of values over time is a great fit for Reactive Extensions for .NET (http://blogs.msdn.com/b/rxteam/). 除了我在下面的原始(剽窃)答案之外,这种情况下你随着时间的推移观察一组值非常适合.NET的Reactive Extensions(http://blogs.msdn.com/b/rxteam /)。 You can get the desired effect with Rx thus: 您可以使用Rx获得所需的效果:
static void Main()
{
var cpuLoadSequence = Observable.GenerateWithTime(
0, // initial value
i => true, // continue forever
i => i + 1, // increment value
i => i, // result = value
i => TimeSpan.FromSeconds(3)); // delay 3 seconds
using (cpuLoadSequence.Subscribe(x => Console.WriteLine("load: {0}%", x)))
{
Console.WriteLine("Press ENTER to stop.");
Console.ReadLine();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.