2012-09-20 78 views
0

我最近從vb.net轉移到C#和我有開創我已創建的Windows服務的問題。我希望該服務在我的app.config文件中每天讀取一次。在vb.net我用了一個定時器,並呼籲方法:在設定時間啓動Windows服務

Private WithEvents Alarm As Timer = New Timer(30000) 
Public Sub OnTimedEvent(ByVal source As Object, ByVal e As ElapsedEventArgs) Handles Alarm.Elapsed 

繼承人的C#代碼,我到目前爲止有:

namespace MyWindowsService 
{ 
class Program : ServiceBase 
{ 
    Timer alarm = new Timer(30000); 
    public string str_dbserver; 
    public string str_year; 
    public string str_time; 
    public string str_dbConnection; 
    bool service_running; 

static void Main(string[] args) 
{ 
    ServiceBase.Run(new Program()); 
} 

public Program() 
{ 
    this.ServiceName = "MyWindowsService"; 
} 


public void OnTimedEvent(object source, ElapsedEventArgs e) 
{  
    service_running = false; 

    //declare variables and get info from config file 
    DateTime dtNow; 
    dtNow = DateTime.Now; 
    System.Configuration.AppSettingsReader configurationAppSettings = new System.Configuration.AppSettingsReader(); 
    str_dbserver = Convert.ToString(configurationAppSettings.GetValue("dbServer", typeof(System.String))); 
    str_year = Convert.ToString(configurationAppSettings.GetValue("sYear", typeof(System.String))); 
    str_time = Convert.ToString(configurationAppSettings.GetValue("stime", typeof(System.String))); 

    //split time from config to get hour, minute, second 
    string[] str_atime = str_time.Split(new string[] { ":" }, StringSplitOptions.None); 

    //check that service is not currently running and time matches config file 
    if (DateTime.Now.Hour == Convert.ToInt32(str_atime[0]) && DateTime.Now.Minute == Convert.ToInt32(str_atime[1]) && service_running == false) 
    { 
     //service now running so write to log and send email notification 
     service_running = true; 

     try 
     { 
      //call functions containing service code here 
      Function1(); 
      Function2(); 
     } 
     catch (Exception ex) 
     { 

     } //end try/catch 

     //service now finished, sleep for 60 seconds 
     service_running = false; 
    } //end if 
} //end OnTimedEvent 

我需要我的代碼來調用OnTimedEvent每30秒檢查時間從配置文件,然後運行我的代碼。任何幫助讚賞

+1

你在哪裏啓動計時器?我在任何地方都看不到。 – Oded

+0

我在服務代碼的OnStart中這樣做:protected override void OnStart(string [] args) { base.OnStart(args); // TODO:將您的起始代碼放在這裏 alarm.Enabled = true; alarm.Start(); } // end onStart –

+0

我編輯了你的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

回答

1

轉儲計時器,啓動線程,使用睡眠(30000)循環。

編輯:更好的是,獲取RTC值並計算在下一次運行時間之前剩餘的ms數。除以2和Sleep()間隔。繼續這樣做,直到間隔小於100ms,然後運行函數Sleep()再次運行1000次(以確保RTC時間現在晚於RTC每天讀取的時間配置文件),並循環。

1

你爲什麼在投票時間?儘管每30秒輪詢一次,在嚴重負載/ ThreadPool飢餓的情況下,可能(儘管極不可能)定時器不會在所需的分鐘時隙中觸發。

爲什麼不計算TimeSpan直到到期時間並設置計時器在那個時間點火?

你不清楚你正在使用哪個計時器,但我不會使用System.Threading.Timer以外的任何其他Windows服務。

+0

+1爲'找出TimeSpan直到到期時間,並設置計時器在那個時候觸發',雖然這個解決方案(和我的)不能很好地處理配置文件中的變化 - 編輯文件時間到較早的時間不會改變等待間隔,直到下一次計時器觸發前一個間隔。 –

0

感謝'Oded'和'Martin James'指引我朝着正確的方向前進。我在解決方案中缺少的是這個。我有下面的代碼添加到構造器類,以便它會認識到,計時器已經過去了:

//call onTimedEvent when timer reaches 60 seconds 
alarm.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
// Set the Interval to 60 second. 
alarm.Interval = 60000; 

然後我用下面的導入KERNEL32 DLL:

using System.Runtime.InteropServices; 

//import kernel32 so application can use sleep method 
    [DllImport("kernel32.dll")] 
    static extern void Sleep(uint dwMilliseconds); 

通過導入此DLL我然後可以使用睡眠(60000)一旦我的代碼完成執行。謝謝大家的幫助

+2

嗯。 'Thread.Sleep'有人嗎? Interop做睡眠?瘋狂的sh * t。 http://msdn.microsoft.com/en-us/library/d00bd51t%28v=vs.80%29.aspx – spender

+0

即時消息不是最有經驗的程序員...什麼是我在這裏做什麼錯?即時通訊不使用線程在我的代碼...但如果我使用system.threading並做一個thread.sleep(60000);這會對我做同樣的事嗎? –

+0

如果你在做什麼對你有用,沒問題。我只是讓你知道Thread.Sleep已經存在於.net中。無需與Windows API進行互操作。 – spender