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.
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
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. 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.
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. To add "an item" you can use Control.BeginInvoke (in winforms) or Dispatcher.BeginInvoke (in wpf).
The code you're using there starts the CheckCPULoad thread, waits 1 second and then aborts it. However, the first thing the CheckCPULoad thread does is to sleep for 3 seconds. So you never actually reach the cpuload++
instruction. 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.
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.
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
Interlocked.Increment(ref cpuload);
Check - http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx
The thread sleeps for 3 secs. You abort it after 1. Go figure :)
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/). You can get the desired effect with Rx thus:
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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.