C#timer定时器总是调用两次

yk鱼 2016-12-02 02:44:14
用C#编写了一个windows定时调用的服务,可是每次到时间都会调用两次,这是为什么?
下面是代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceProcess;
using System.Text;
using System.Timers;

namespace wxTemplateMessage
{
public partial class Service1 : ServiceBase
{
Timer tmTimer = new Timer();
string WechatTemplateMessage;//接收调用发送模板消息后的返回值
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
tmTimer.Interval = 1000 * 60;
tmTimer.Elapsed += new System.Timers.ElapsedEventHandler(time1_SendTemplateMessage);
tmTimer.Enabled = true;
}
protected override void OnStop()
{
this.tmTimer.Enabled = false;
}
private void time1_SendTemplateMessage(object sender, System.Timers.ElapsedEventArgs e)
{
// 得到 hour minute second 如果等于某个值就开始执行某个程序。
int intHour = e.SignalTime.Hour;
int intMinute = e.SignalTime.Minute;
int intSecond = e.SignalTime.Second;
// 定制时间; 比如 在10:30 :00 的时候执行某个函数
int iHour = 17;
int iMinute = 00;
int iSecond = 00;

if (intHour == iHour && intMinute == iMinute)
{
WechatTemplateMessage = GetHtml("http://www.xxxxxx.cn/xxxxxxx/TemplateMessage.aspx");
}
}
//get请求
private string GetHtml(string url)
{
WebClient clinet = new WebClient();//定义一个客户端的对象
//打开url,get参数以url后缀的方式就可以传递过去。
Stream stream = clinet.OpenRead(url);//吧url放到地址栏里去按回车
clinet.UploadData(url, Encoding.UTF8.GetBytes(""));
//把从http中返回的流读为string
StreamReader reader = new StreamReader(stream);
string result = reader.ReadToEnd();
return result;
}
}
}
...全文
1961 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
ldcmay 2017-08-14
  • 打赏
  • 举报
回复 1
解决方法: 将定时器事件注册程序写到外面,你想啊,你点一下按钮,注册一次事件,肯定要执行多次的。 我就是这么解决的
yk鱼 2017-05-03
  • 打赏
  • 举报
回复
去年了写了就一直没时间再弄,最近项目启动需要用到又重新写了一下,加了日志还有利用VS附加进行了调试,最后发现问题可能是get请求的问题。

    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            EventLog.WriteEntry("模板消息定时发送服务启动");//在系统事件查看器里的应用程序事件来源的描述
            WriteLog("服务启动1");//自定义日志
            System.Timers.Timer time = new System.Timers.Timer();
            time.Interval = 1000*60;
            //time.Elapsed += new System.Timers.ElapsedEventHandler(SendTemplateMessage);
            time.Elapsed += SendTemplateMessage;//到达时间执行事件
            time.AutoReset = true;//设置是执行一次(FALSE)还是一直执行(true)
            time.Enabled = true;//是否执行System.TImers.Timer.Elapsed事件
        }

        private void SendTemplateMessage(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                int intHour = e.SignalTime.Hour;
                int intMinute = e.SignalTime.Minute;
                int intSecond = e.SignalTime.Second;

                string gisdataSend = ConfigurationManager.AppSettings["DataSend"].ToString();
                string gisdataPath = ConfigurationManager.AppSettings["DataSendPath"].ToString();
                string gisdataHoure = ConfigurationManager.AppSettings["DataIntHour"].ToString();               
                string gisdataMinute = ConfigurationManager.AppSettings["dataIntMinute"].ToString();

                string moveSend = ConfigurationManager.AppSettings["MoveSend"].ToString();
                string movePath = ConfigurationManager.AppSettings["MoveSendPath"].ToString();
                string moveHoure = ConfigurationManager.AppSettings["MoveIntHour"].ToString();
                string moveMinute = ConfigurationManager.AppSettings["MoveIntMinute"].ToString();

                //if (intHour == Convert.ToInt32(moveHoure) && intMinute == Convert.ToInt32(moveMinute))//定时设置,判断分时秒
                if (intHour == Convert.ToInt32(moveHoure) && intMinute == Convert.ToInt32(moveMinute))//定时设置,判断分时秒
                {
                    if (moveSend == "1")
                    {
                        System.Timers.Timer tt = (System.Timers.Timer)sender;
                        tt.Enabled = false;

                        //var result = GetHtml(movePath);
                      var result =  SendGetHttpRequest(movePath, "application/x-www-form-urlencoded");
                        WriteLog(result);

                        tt.Enabled = true;
                    }
                }
                if (intHour == Convert.ToInt32(gisdataHoure) && intMinute == Convert.ToInt32(gisdataMinute))//定时设置,判断分时秒
                {
                    if (gisdataSend == "1")
                    {
                        System.Timers.Timer tt = (System.Timers.Timer)sender;
                        tt.Enabled = false;

                        //var result = GetHtml(gisdataPath);
                        var result = SendGetHttpRequest(gisdataPath, "application/x-www-form-urlencoded");
                        WriteLog(result);

                        tt.Enabled = true;
                    }

                }

            }
            catch (Exception ex)
            {

                WriteLog(ex.ToString());
            }           
        }

        private string SendGetHttpRequest(string url, string contentType)
        {
            WebRequest request = (WebRequest)HttpWebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = contentType;
            string result = string.Empty;
            using (WebResponse response = request.GetResponse())
            {
                if (response != null)
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                        {
                            result = reader.ReadToEnd();
                        }
                    }
                }
            }
            return result;
        }
        protected override void OnStop()
        {
            WriteLog("服务停止");
            EventLog.WriteEntry("服务停止");   
        }

        //日志
        public void WriteLog(string readme)
        {
            string logPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

            StreamWriter dout = new StreamWriter(logPath + "WechatLog.txt", true);
            dout.Write("\r\n事件:" + readme + "\r\n操作事件:" + System.DateTime.Now.ToString("yyy-MM-dd HH:mm:ss"));

            dout.Close();
        }
最后附上调试Windows服务的链接https://msdn.microsoft.com/zh-cn/library/7a50syb3(v=vs.110).aspx
ztmsimon 2016-12-13
  • 打赏
  • 举报
回复
timer最好是不要用,以你现在的状态,我看也是难得掌握好timer这个组件。你觉得使用起来方便,但是后面的坑会让你哭。
Benjay77 2016-12-07
  • 打赏
  • 举报
回复
要不试试Threading.Timer 总感觉Winform.Timer 老是会有各种问题
痛苦的火龙果 2016-12-07
  • 打赏
  • 举报
回复
引用 13 楼 qaz2499867 的回复:
tmTimer.Elapsed += new System.Timers.ElapsedEventHandler(time1_SendTemplateMessage); 这段代码是不是执行了两次
可以试试 在+=之前 tmTimer.Elapsed =null;或者调用一次 -=
痛苦的火龙果 2016-12-07
  • 打赏
  • 举报
回复
tmTimer.Elapsed += new System.Timers.ElapsedEventHandler(time1_SendTemplateMessage); 这段代码是不是执行了两次
youzelin 2016-12-07
  • 打赏
  • 举报
回复
把 Timer 的 Interval 改成 60 秒以上,比如 65 秒,再试试
golden24kcn 2016-12-07
  • 打赏
  • 举报
回复
在time1_SendTemplateMessage事件中加入 if (intHour == iHour && intMinute == iMinute) { WechatTemplateMessage = GetHtml("http://www.xxxxxx.cn/xxxxxxx/TemplateMessage.aspx"); timer1.enable=false; }
njit_77 2016-12-06
  • 打赏
  • 举报
回复 1
引用 2 楼 Libby1984 的回复:
你断点看一下,会不会是你的OnStart函数由于某些原因执行了2次,导致你注册了两次定时器事件。
看下是不是注册了两次,以前碰到这个现象,发现事件注册了多次
  • 打赏
  • 举报
回复
设计程序流程的逻辑应该有些“余量”,不能靠“碰巧”去设计。 比如说,如果你想 17点0分的时候执行一次某过程,那么你的 Timer 的 Interval 不管是设置为1分钟还是10秒钟,你的程序的逻辑看起来都会在17点0分的时候仅仅执行一次这个过程(尽管Timer 在这一分钟内可能会触发1次、2次、6次或者7次)。 加强你的逻辑设计吧。
张久奎 2016-12-02
  • 打赏
  • 举报
回复 2
绑定事件那儿不要再用new了,直接在+=后面写上函数名就可以了,
crystal_lz 2016-12-02
  • 打赏
  • 举报
回复
你OnStart就会绑定一次事件 如果stop再start 那么就会再绑定
SoulRed 2016-12-02
  • 打赏
  • 举报
回复
我觉得你是不是用了多线程?同一时间有两段代码调用了这个函数
by_封爱 版主 2016-12-02
  • 打赏
  • 举报
回复
SignalTime我没用过.我都是跟当前时间对比... 没遇到过什么问题.. 或者使用quarzt.net调度 不用timer...
事理 2016-12-02
  • 打赏
  • 举报
回复
protected override void OnStop() { this.tmTimer..Stop(); this.tmTimer.Enabled = false; } 这里是不是少了个秒的判断?不加上可能会下载页面不止两次 if (intHour == iHour && intMinute == iMinute) {
yk鱼 2016-12-02
  • 打赏
  • 举报
回复
引用 3 楼 guonan198811 的回复:
单独起一个线程跑时钟程序,或者定义时钟的触发事件,放到构造函数中去执行。你当前的程序,没有循环判断和执行的代码
要执行的代码WechatTemplateMessage = GetHtml("http://www.xxxxxx.cn/xxxxxxx/TemplateMessage.aspx");要执行的代码放TemplateMessage.aspx这个网页里了,所以是调用这个TemplateMessage.aspx页面就可以了
yk鱼 2016-12-02
  • 打赏
  • 举报
回复
Dispose了也一样,调用了两次
南天空 2016-12-02
  • 打赏
  • 举报
回复
单独起一个线程跑时钟程序,或者定义时钟的触发事件,放到构造函数中去执行。你当前的程序,没有循环判断和执行的代码
  • 打赏
  • 举报
回复
你断点看一下,会不会是你的OnStart函数由于某些原因执行了2次,导致你注册了两次定时器事件。
  • 打赏
  • 举报
回复
OnStop中将timer Dispose 一下

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧