前兩天寫了一個定時發送天氣預報的程式,老是出現這樣或那樣的bug,甚至有時候出現拒絕服務的錯誤。去網上找了一下資料,發現是自己的定點發送存在一定的問題。現在總結一下經驗,並和大家一起探討一下。
首先我們要使用global.asax中的事件,在Application_Start事件中啟動我們的任務,在Application_End中停止我們的任務。 當然啟動我們的任務,必須是啟動一個線程去完成相應的工作。
開始,我線上程中做的事情是每隔900ms判斷一下,當前的事件是否等於指定的時間,如果等於的話,就執行相應的任務,但是這樣容易出現的毛病就是訪問太頻繁了,佔用過多的cpu資源。
後來,我想到的方法是,計算現在到定點時間的ms數,由以下函數完成:
private int GetSleepTime(int hour, int min, int second)
{
DateTime now = DateTime.Now;
int sleep = (((hour - now.Hour) * 60 + (min - now.Minute)) * 60 + (second - now.Second)) * 1000;
if (sleep < 0)
sleep += 24 * 3600 * 1000;
return sleep;
}
這樣直接sleep到指定的事件點就可以了,然後再執行我們的任務。
為了能夠中途能夠認為停止,用sleep就不是很方便了,所以我決定用wait,具體的線程方法如下:
private void Run()
{
while (isStart)
{
int sleep = GetSleepTime(19, 0, 0);
lock (locker)
{
Monitor.Wait(locker, sleep);
}
if (isStart)
SendWeatherReport(); // 這是我要定點完成的工作
}
}
當要中途停止的時候,我們調用如下方法:
public void Stop()
{
isStart = false;
lock (locker)
{
Monitor.PulseAll(locker);
}
}
這樣我們的目的就要到達了。但後來我發現,第二天早上還是收不到天氣預報資訊,去網上查了一下,發現asp.ne程式,再一段時間不訪問後會被回收。網上也找到了比較猥瑣的解決辦法,想找其他不猥瑣的辦法,但是目前還沒有找到,或者是一些不太可行的辦法。
就是在Application_End事件中,去訪問我們的程式,重新啟用應用程式。
void Application_End(object sender, EventArgs e)
{
// 在應用程式關閉時啟動並執行代碼
job.Stop();
string url = "http://locahost/weatherreport/default.aspx"; // 在這裡指定你的該asp.net程式的地址
HttpWebRequest myHttpWebRequest = null;
HttpWebResponse myHttpWebResponse = null;
StreamReader sr = null;
Stream receiveStream;
string str = null;
try
{
myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
receiveStream = myHttpWebResponse.GetResponseStream();
sr = new StreamReader(receiveStream, Encoding.UTF8);
str = sr.ReadToEnd(); // 這句話,貌似沒有是不行的,否則啟用不了
}
catch
{
}
finally
{
if (sr != null)
sr.Close();
if (myHttpWebResponse != null)
myHttpWebResponse.Close();
}
}
總結也就這麼多了,接下來的時間該做畢設了。