前两天写了一个定时发送天气预报的程序,老是出现这样或那样的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();
}
}