如何让线程“回报”到主线程?

时间:2010-12-27 10:15:53

标签: c# multithreading

我正在创建一个监视计算机上的内容的应用程序,我想让它更难以实现一个while循环。

所以我的问题是如果我想在一个单独的线程中获取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
        }
    }
}

因为每次都会打印“load:0%”。我需要修复什么才能让它显示

load: 0% 
load: 0% 
load: 0% 

感谢

8 个答案:

答案 0 :(得分:3)

为了“回报”主线程,主线程必须是“监听”。这意味着,仍然在while循环中运行并检查某种类型的队列以查找代表报告的新项目。

您基本上需要的是一个队列,其中工作线程将放置其报告,主线程将定期检查此队列以获取该工作人员的报告。

您有两种主要方法:

  1. 阻止队列。意味着什么时候 调用者线程没有项目 阻止物品到达。这是 如果主线程什么都没有,那就好了 除了等待中的项目 队列中。
  2. 非阻塞队列。意味着它 立即返回给调用者 无论物品数量多少。这个 如果你想要你的主线程是好的 忙着做事有时候 检查队列中的报告。
  3. 如果您的应用程序是UI应用程序,您将自动获得第一种方法,因为这是UI的工作方式。要添加“项目”,您可以使用Control.BeginInvoke(在winforms中)或Dispatcher.BeginInvoke(在wpf中)。

答案 1 :(得分:1)

你在那里使用的代码启动CheckCPULoad线程,等待1秒然后中止它。但是,CheckCPULoad线程做的第一件事就是睡3秒钟。所以你永远不会真正达到cpuload++指令。我怀疑这会更接近你的意图:

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++;
            }
        }
    }
}

答案 2 :(得分:1)

使用计时器和事件。这样可以避免您的睡眠/忙碌等待。如果多个线程可以同时修改静态变量,也可以考虑使用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();
        }
    }
}

答案 3 :(得分:1)

如果我找对你,这应该可以解决你的目的。注意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++;
        }
    }


}

答案 4 :(得分:0)

而不是cpuload++尝试使用

Interlocked.Increment(ref cpuload);

检查 - http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx

答案 5 :(得分:0)

线程休眠3秒。你在1之后中止它。去图:)

答案 6 :(得分:0)

使用callback即可

这是一个例子:

答案 7 :(得分:0)

除了我下面的原始(抄袭)答案之外,这种情况下你随着时间的推移观察一组值非常适合.NET的Reactive Extensions(http://blogs.msdn.com/ b / rxteam /)。您可以使用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();
    }
}