2013-01-23 34 views
1

我正在編寫一個程序,有幾個「工人」對象關閉,並執行任務設置的時間量。我創建了一個工作正常的內部計時器。但是,在做「工作」時,我有時需要等待幾秒鐘才能刷新屏幕(每個工作人員正在從遠程屏幕上抓取數據並進行一些自動操作)。暫停程序不中斷定時器c#

對於那些暫停,我不想睡覺的線程,因爲據我所知,這也將 暫停在其他工人對象的計時器(我的應用程序是一個單一的線程,因爲,坦率地說,我是品牌新的C#和我不想超越)。是否還有另一個等待函數可以使用,它並不實際掛起整個線程?

一些額外的信息:

  • 現在這是一個控制檯應用程序,但我最終將構建UI的形式來提供反饋給用戶如何工人正在做
  • 我定時器實現使用System.Timers和正在工作很好
  • 我是C#編程新品,這是我的第一個項目,所以請用小字;)
  • 使用MS VS Express 2012的桌面(所以無論版本的C#/ .NET是!)

下面的代碼(實際的工作將使用「startWorking」方法完成,但沒有實現 - 這只是我的銷售版本與定時器工作。此外,主要只是用於測試多個計時器)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Timers; 

namespace Multi_Timers 
{ 
//worker class that includes a timer 
public class Worker 
{ 
    private Timer taskTimer; 
    private bool available = true; 
    private string workerName; 
    private string startWork; 
    private int workTime; 

    // properties 
    public bool isAvailable { get { return this.available; } } 
    public string name { get { return this.workerName; } } 

    // constructor 
    public Worker(string name) 
    { 
     this.workerName = name; 
     Console.WriteLine("{0} is initialized", name); 
    } 

    // start work timer 
    public void startWorking(int duration) { 

     if (this.available == true) 
     { 
      this.available = false; 
      this.taskTimer = new Timer(); 
      this.taskTimer.Interval = duration; 
      this.taskTimer.Elapsed += new ElapsedEventHandler(doneWorking); 
      this.taskTimer.Enabled = true; 
      this.startWork = DateTime.Now.ToString(); 
      this.workTime = duration/1000; 
     } 
     else Console.WriteLine("Sorry, {0} was not available to work", this.workerName); 
    } 

    // Handler for timer 
    public void doneWorking(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("{0}: {1}/{2} min/{3}", this.workerName, this.startWork, this.workTime/60, e.SignalTime.ToLocalTime()); 
     this.taskTimer.Enabled = false; 

     this.available = true; 

    } 
} 

//main program 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Random r = new Random(); 

     // initialize worker(s) 
     Worker bob = new Worker("Bob"); 
     Worker bill = new Worker("Bill"); 
     Worker jim = new Worker("Jim"); 

     // q to exit 
     while (true) 
     { 
      if (bob.isAvailable) { 

       bob.startWorking(r.Next(1 * 60, 150 * 60) * 1000); 
      } 
      if (bill.isAvailable) 
      { 
       bill.startWorking(r.Next(1 * 60, 150 * 60) * 1000); 
      } 
      if (jim.isAvailable) 
      { 
       jim.startWorking(r.Next(1 * 60, 150 * 60) * 1000); 
      } 

     } 
    } 
} 
} 

謝謝你的任何幫助提前!閱讀這個社區的例子,絕對是讓我自己學習一點C#開始的關鍵!

回答

2

我不想睡覺線程,因爲按照我的理解,也將暫停對其他工人的定時器對象

這是不正確;它不會停止定時器。

我的應用程序是一個單獨的線程

不,實際上,事實並非如此。定時器將創建並使用其他線程來實現其行爲。 Elapsed事件處理程序將從線程池線程中觸發。與您的代碼


的一個主要問題是,你的main方法做的三個對象「busywait」,不停地輪詢他們詢問他們是否就大功告成了。這是...昂貴。基本上就像你在問孩子,「我們到了那裏了。」每秒幾百次。如果他們只是坐在他們的等待中,直到你告訴他們你已經完成了,他們會不會更好? (這很可能,也是一個很好的選擇。)

在這種情況下更簡單的解決方案之一是在工作人員中做循環,而不是Main。執行startWorking包裝在一個while循環中,並且主要只是做一個永遠的等待(即Thread.Sleep(Timeout.Infinite);)。更復雜的選擇是讓工作人員提供一個Task事件或阻止等待(也稱爲「加入」)方法來指示它們何時完成。

你正在考慮的選項,在Main幫助加入了一小會兒的Thread.Sleep,但它只是告訴你的孩子問你,當你不經常,而不是讓他們等待在那裏你在什麼時候告訴他們。

+0

謝謝,我不知道他們的自動產生的線程爲自己,這是偉大的!對於主要的東西,我也欣賞幾種不同方法的建議。現在,它真的只是測試我的方法,肯定會在未來做一些更優雅的事情! – Adrian

0

如果你發現自己想在不同的上下文中再延遲執行的,你可以考慮這樣的實現:

private static void DelayExecution(Action action, TimeSpan delay) 
{ 
    TimeSpan start = DateTime.Now.TimeOfDay; 
    Thread t = new Thread(() => 
    { 
     while (DateTime.Now.TimeOfDay < start.Add(delay)) 
     { 
      //Block 
     } 
     action.Invoke(); 
    }); 
    t.Start(); 
} 

private static void Main(string[] args) 
{ 
    DelayExecution(() => Console.WriteLine("Delayed Execution"), TimeSpan.FromSeconds(1)); 
    Console.ReadLine(); 
} 
+0

謝謝,還會記住這一點! – Adrian