簡體   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