2011-04-02 71 views
0

我从来不必多次使用线程 - 只有少数几次。但今天,我很无聊,想和他们一起玩,并尝试建立一种理解。它看起来像BackgroundWorkerThread是一件好事...所以,我试图做一个控制台应用程序,只需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."); 
     } 

    } 
} 

但它似乎凌乱。任何人都可以帮助我向我展示它应该如何完成?

回答

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

,或者你只是使用上如何防止重启定时器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

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

虽然有几件事情可以改善。首先,你的while循环不需要一个刚被设置为IsBusy的运行变量。只需直接检查IsBusy。此外,您应该在循环中进行某种睡眠以避免无用地过度使用CPU。检查之间休息10毫秒会有很大帮助。其次是一个建议,对于比这更实际的程序,使用RunWorkerCompleted事件来提醒它何时完成,而不是经常检查它。这导致更简单和更灵活的代码。

最后一件事,特别是GUI程序,是了解ProgressChanged事件。在你的工作方法中设置它,并通过你的GUI访问它,你可以很容易地用工作线程的进度更新接口。请记住,除了GUI线程之外,您不能从任何线程更新GUI。