简单的线程问题

时间:2011-04-02 03:14:32

标签: c# multithreading

我从来没有多次使用线程 - 只有少数几次。但今天,我很无聊,想和他们一起玩......并尝试建立一种理解。它看起来像 BackgroundWorkerThread 是一件好事......所以,我尝试制作一个控制台应用程序,简单地写入'Tick'5秒,5次。这就是我想出来的:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BackgroundWorker bw = new BackgroundWorker();

            AlarmClock ac = new AlarmClock(5);
            bw.DoWork += ac.StartAlarm;
            bw.RunWorkerAsync(5);

            bool run = true;

            while(run)
            {
                run = bw.IsBusy;  
            }
            Console.WriteLine("Finished!!");
            Console.WriteLine("Press a key...");
            Console.ReadKey();
        }
    }

    public class AlarmClock
    {
        private int noOfTicks;

        public AlarmClock (int noOfTicks)
        {
            this.noOfTicks = noOfTicks;
        }

        public void StartAlarm(object sender, DoWorkEventArgs e)
        {
            DateTime start = DateTime.Now;
            Console.WriteLine("Alarm set to tick ever 5 seconds.");
            int ticks = 0;
            bool runMe = true;

            while (runMe)
            {
                if (DateTime.Now.Second % 5 == 0)
                {
                    Console.WriteLine("Tick..");
                    ticks++;
                    Thread.Sleep(1000);
                }
                runMe = ticks < noOfTicks;
            }
            Console.WriteLine("Aboring thread.");
        }

    }
}

但它似乎很乱。谁能协助我告诉我应该怎么做?

4 个答案:

答案 0 :(得分:2)

或者您只是使用System.Threading.Timer

System.Threading.Timer aTimer = new System.Threading.Timer(OnTimedEvent, null, 5000, 5000);

private static void OnTimedEvent(Object stateInfo)
{
    Console.WriteLine("Hi");
}

有关如何防止计时器重启的更多信息,请立即重新启动计时器,在此link禁用定期信令。

要了解.NET中不同计时器之间的差异,请访问此link

答案 1 :(得分:1)

对于你正在做的事情,你想要使用timer

 public static void Main()
 {
     System.Timers.Timer aTimer = new System.Timers.Timer();
     aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
     // Set the Interval to 5 seconds.
     aTimer.Interval=5000;
     aTimer.Enabled=true;

     Console.WriteLine("Press \'q\' to quit the sample.");
     while(Console.Read()!='q');
 }

 // Specify what you want to happen when the Elapsed event is raised.
 private static void OnTimedEvent(object source, ElapsedEventArgs e)
 {
     Console.WriteLine("Hello World!");
 }

答案 2 :(得分:1)

如上所述,对于所描述的情况,Timer比BackgroundWorker更有效。但如果你的目标是学习如何使用BackgroundWorker类,你可以这样做:

class Program
{
    static void Main()
    {
        var worker = new BackgroundWorker {WorkerReportsProgress = true};
        worker.DoWork += DoWork;
        worker.ProgressChanged += ReportProgress;
        worker.RunWorkerAsync(5);

        Console.ReadKey();
    }

    private static void DoWork(object sender, DoWorkEventArgs e)
    {
        int count = (int) e.Argument;
        for (int i = 1; i <= count; i++)
        {
            (sender as BackgroundWorker).ReportProgress(i);
            Thread.Sleep(5000); // Do your work
        }
    }

    private static void ReportProgress(object sender, ProgressChangedEventArgs e)
    {
        Console.WriteLine("Tick " + e.ProgressPercentage);
    }
}

答案 3 :(得分:1)

实际上看起来很不错。不计算你的闹钟类,因为它只代表工作代码,它只是做你需要做的事情,你对后台工作者做的唯一事情是添加一个事件,调用一个方法,并等待IsBusy为假。那里什么都没有。

但是你可以改进一些东西。首先,你的while循环不需要一个只设置为IsBusy的运行变量。直接检查IsBusy。此外,你应该在循环中放置一些睡眠,以避免无用的CPU过度负担。事件之间,检查之间的剩余10毫秒将有很大帮助。对于比这更真实的程序,第二个是建议使用RunWorkerCompleted事件在完成时发出警报,而不是经常检查它。这样可以实现更简单,更灵活的代码。

最后一件事,尤其是GUI程序,是了解ProgressChanged事件。在您的工作方法中设置它,并从GUI访问它允许您使用工作线程的进度轻松更新界面。请记住,除了GUI线程之外,您永远不能从任何线程更新GUI。