2012-07-05 72 views
0

我正在開發一個項目,我需要讓用戶創建一個(或多個)定時器來觸發事件。 用戶應該定義變量,例如計時器是否應該激活以及計時器多長時間一次觸發以及計時器變化時會發生什麼其他變量。多個動態定時器

所有這些變量被存儲在字典(Disctionary),其中物體保持用戶已設置的所有的變量和該字符串的名稱,用戶已經選擇用於這個定時器。

然後我想我的程序遍歷該字典,並搜索具有可變t_Active設置爲true的所有對象(這我已經實現)。 我需要幫助的是以下幾點: 當它檢測到變量,並且它被設置爲true時,我需要程序來查看是否已經爲此創建了一個計時器。 如果不是,它應該創建一個併爲計時器設置相關參數。 兩個變量t_num和t_period應決定計時器的時間間隔。 t_num是一個int,t_period是一個字符串,它將被設置爲分鐘,小時或天數。

結合與60000(分鐘)t_num,3600000(小時)或86400000應該給CORRCT間隔。

但是,我將如何繼續爲每個用戶定義的活動對象編程創建一個計時器? 如何讓程序檢測是否已經創建了定時器?

我一直在尋找在這裏和谷歌,但到目前爲止,我還沒有碰到過的東西,對我來說很有意義來。 我仍然在學習C#,所以對你們來說有意義的東西可能不會對我有意義。 :)

我希望我已經explaned我所需要的足夠好,請不要問我,如果你不幫我澄清。

編輯:

也許我還應該提到的是,提到的字典也將被保存到一個XML文件,用戶可以拿起他們在任何時候做出的所有設置。

編輯2:

@hatchet我想知道用是否這會工作。 我試圖讓它工作,但碰到一些困難(因爲我缺乏經驗,並沒有完全理解你的僞代碼,我得到的錯誤,我可以解決的一些錯誤,以及一些我(我沒有期待完整的工作代碼,不用擔心))。

此外,用戶應該能夠修改計時器。 在mainform中,有幾個文本框和三個按鈕。 表單用於發送消息。 用戶可以選擇手動發送消息,將消息添加到計時器或編輯計時器。

當用戶點擊手動按鈕時,消息會發送給所有接收者一次。 如果添加的消息的計時器,一個新的子窗體彈出時,他們都能夠設置以下詳細信息,其中: 字符串名稱 日期時間開始_ 複選框結束 日期時間END_DATE 的NumericUpDown秒(定時器)(15最小值分鐘) 組合框分鐘,小時,天 複選框主動

當用戶將消息添加到定時器時,TimerSettings獲取到字典爲刺痛,對象(我的自定義對象cointaing所有細節)。

如果他們點擊主窗體上的修改按鈕,則認爲在子窗體打開之前,程序查找相應的定時器(mainform具有帶所有添加的定時器的組合框),停止定時器,然後打開該子表單讓用戶編輯細節。

在子窗體上也是一個刪除按鈕,以便用戶可以刪除定時器。

當添加或修改計時器時,mainform捕捉它並將更改寫入XML文件和組合框。 這裏是它應該看的地方,如果已經有一個這個消息的計時器並且沒有創建,或者如果有的話重新啓動計時器。

我不知道我應該如何讓你的解決方案爲此工作。 發送消息的過程從30秒到5分鐘取決於接收器的數量(不能超過42個(該程序是另一個不允許超過42個接收器的程序的接口))的任何事情) 。

我明白幾個定時器可能是一個問題,但我懷疑任何用戶都需要超過最多10個定時器,所以可能會有15個定時器的內置限制。

+1

你只需要一個定時器,當所有不同的目標中最接近的一個被預定發生時,該定時器就會被觸發。它可以處理所有這些。 – hatchet

+0

我不知道如何用你的建議完成我所需要的。假設我有一個定時器每隔一秒就會關閉,如果用戶有,可以說5個事件,他們全都設置爲在完全不同的時間點火,那麼如何確定要觸發哪個事件? 你能提供一個僞示例嗎? – Rickard

回答

0

這是一種C#代碼,用來表達想法。我做了同樣的事情,但是有足夠的細節不同,粘貼代碼會令人困惑。因此,除了我的頭頂,這個半碼將有望足夠接近真正的代碼,向您展示我對您的問題的評論意味着什麼。

說你有一個像這樣

public delegate void Work(); 

public class TimedThing { 
    public int IntervalSecs; 
    public DateTime NextFiring; 
    public event Work OnWork;   
} 

一類。然後你有一個控制器類

public class TimedGroup { 
    TimedThing[] things; 
    System.Timers.Timer timer; 

    public TimedGroup() { 
     this.timer = new System.Timers.Timer(); 
     this.timer.AutoReset = false; 
     this.timer.Elapsed += TimerFired; 
    } 
      ... 
    // some methods for adding and removing TimerThings 
      ... 
    public void Start() { 
     this.timer.Interval = 1; // just to get things started 
     this.timer.Enabled = true; 
    } 
    public void Stop() { 
     this.timer.Enabled = false; 
    } 
    private void TimerFired(object sender, System.Timers.ElapsedEventArgs e) { 
     DateTime now = DateTime.Now; 
     // let's have timer fire at least as frequently as every 5 minutes 
     // if we need to have it fire sooner than that, it will get set below 
     DateTime next = now.AddMinutes(5); 
     foreach(var thing in this.things) { 
      if (thing.nextFiring <= now) { 
       var task = Task.Factory.StartNew(() => DoWork(thing)); 
       thing.NextFiring = thing.NextFiring.AddSeconds(thing.IntervalSeconds); 
       // or maybe this is more appropriate 
       // thing.NextFiring = Now.AddSeconds(thing.IntervalSecs); 
      } 
      if (thing.NextFiring < next) next = thing.NextFiring; 
     } 
     // set the timer to fire whenever the next soonest work needs to be done 
     this.Timer.Interval = (next - now).TotalMilliseconds; 
     this.Timer.Enabled = true; 
    } 
    private void DoWork(TimedThing thing) { 
     thing.Work(); 
    } 
} 

有可能的細節,雖然有要處理的,儘管其中許多細節都處理你是否在爲每件事物使用計時器,或者爲他們全部使用一個計時器。例如,如果一件東西的工作通常需要10秒鐘,但偶爾可能需要60秒,而且他們的時間間隔設置爲45秒。有時下一次射擊會再次運行該工作,儘管之前的工作開始於前一次射擊仍在運行。這可能會也可能不是理想的,取決於這些事情在做什麼樣的工作。如果不可取,​​則必須添加一些監視任務的產生,以便知道是否需要跳過這項工作,因爲以前的工作尚未完成。另一件事是編寫一個優雅的曲線。當您將timer.Enabled設置爲false(或timer.Stop()...這是同一件事)時,即使停止計時器,計時器事件仍然可以發生短暫的一段時間(請參閱Why does System.Timer.Timer still fire events when Enabled is set to false? )。這可能會導致一些奇怪的行爲/錯誤。

1

我不確定定時器如何使用該方法進行擴展。可能值得研究管理這些事件的其他方法。正如@hatchet剛剛發表了評論,您可以爲下一個事件設置1個計時器。採用這種方法,您可以在運行時設置下一個計時器。

另一種可能性是使用一個數據庫和一個定時器,該定時器每運行一個小時間段>就會執行所有帶有適當時間戳的動作。

+0

這聽起來很像「數據庫作爲隊列」反模式。 –