繁体   English   中英

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

[英]How can i make a thread “report back” to main thread?

我正在制作一个应用程序,监视我的计算机上的东西,我想让它更难以实现一个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% 

谢谢

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

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

您有两种主要方法:

  1. 阻塞队列。 意味着当没有项目时,调用者线程将阻塞直到项目到达。 如果主线程除了等待队列中的项目之外没有任何操作,这是很好的。
  2. 非阻塞队列。 意味着无论项目数是多少,它都会立即返回给调用者。 如果您希望主线程忙于执行操作并且有时检查队列中的报告,那么这很好。

如果您的应用程序是UI应用程序,则会自动获得第一种方法,因为这是UI的工作方式。 要添加“项目”,您可以使用Control.BeginInvoke(在winforms中)或Dispatcher.BeginInvoke(在wpf中)。

你在那里使用的代码启动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++;
            }
        }
    }
}

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

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


}

而不是cpuload++尝试使用

Interlocked.Increment(ref cpuload);

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

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

通过回调,您可以做到这一点

这是一个例子:

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

除了我在下面的原始(剽窃)答案之外,这种情况下你随着时间的推移观察一组值非常适合.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();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM