2011-04-02 69 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。