在Windows服务中无限循环

时间:2014-08-30 08:43:44

标签: c# windows-services infinite-loop

我有一个窗口,我在OnStart()方法中添加了一个无限的while循环。我已经测试了1小时的服务并且运行正常。但这是我的第一个Windows Service所以有怀疑无限循环的性能。 这是代码..

 protected override void OnStart(string[] args)
    {
       while(true){

        string Query="";

        Query = "SELECT * FROM 'reportsetting` order by SendingTime;";

        MySqlConnection con = new MySqlConnection(conn);
        MySqlCommand comm = new MySqlCommand(Query, con);
        con.Open();
        MySqlDataReader dr = comm.ExecuteReader();
        while (dr.Read())
        {

            time = dr["SendingTime"].ToString();

            if ((str = DateTime.Now.ToString("HH:mm")).Equals(time))
            {

                //Execute Function and send reports based on the data from the database.

                Thread thread = new Thread(sendReports);
                thread.Start();

            }


        }


            //Halt for this Moment

            while ((str = DateTime.Now.ToString("HH:mm")).Equals(time))
            {


            }


         }

        }

    public void sendReports() { 



    }

所以想知道长跑是否合适。谢谢..

4 个答案:

答案 0 :(得分:4)

您几乎肯定不想在无限循环中查询数据库。您可能想要做的是使用Timer每隔一段时间(例如每30秒)查询一次数据库,并在某些情况匹配时做一些工作,例如。

private static Timer timer;
private const int TimerInterval = 30000;

protected override void OnStart(string[] args)
{
    var callback = new TimerCallback(checkDatabase);
    this.timer = new Timer(callback, null, 0, TimerInterval);
}

private void checkDatabase()
{
    string query = "SELECT * FROM 'reportsetting` order by SendingTime;";
    using (var con = new MySqlConnection(conn))
    using (var cmd = new MySqlCommand(query, con))
    {
        con.Open();
        using (var dr = cmd.ExecuteReader())
        {
            while (dr.Read())
            {
                // do some work
            }
        }
    }
}

根据更新速度的重要程度,您还可以了解情况并引入补偿策略。例如,这是一个非常简单的增量退避:

private const int DefaultInterval = 40000;
private int interval = DefaultInterval;
...

while (dr.Read())
{
    if (someCondition)
    {
        // do some work
        timer.Change(DefaultInterval, DefaultInterval); // revert to 40 seconds 
    }
    else 
    {
        // no change? increase polling by 10 seconds
        interval += 10000;
        timer.Change(interval, interval);
    }
}

答案 1 :(得分:4)

每40秒重新运行一次查询:

private const string Query = "SELECT * FROM 'reportsetting` order by SendingTime;"

protected override void OnStart(string[] args)
{
    _timer = new Timer(40 * 1000); // every 40 seconds
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
    _timer.Start(); // <- important
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    MySqlConnection con = new MySqlConnection(conn);
    MySqlCommand comm = new MySqlCommand(Query, con);
    con.Open();
    MySqlDataReader dr = comm.ExecuteReader();
    while (dr.Read())
    {

        time = dr["SendingTime"].ToString();

        if ((str = DateTime.Now.ToString("HH:mm")).Equals(time))
        {

            //Execute Function and send reports based on the data from the database.

            Thread thread = new Thread(sendReports);
            thread.Start();
        }
    }
}

这样的事情。 正如Groo所提到的那样,你可能希望每次都处理这种连接,这样你就不会在内存中闲置它。

答案 2 :(得分:1)

试试这个

bool _IsStop = false;

protected override void OnStart(string[] args)
{
        base.OnStart(args);

        while (!this._IsStop)
        {

            this.Process();

            //40 seconds time out
            Thread.Sleep(1000*40); //1000 is 1 second
        }

        //If we reach here
        //Do some clean up here

    }


    protected override void OnStop()
    {
        //Service is stop by the user on service or by OS
        this._IsStop = true;

    }


    private void Process()
    {
        string Query = "";

        // -->>>  if you use something like this on your query and little bit setup on your db
        // this will give you a more efficient memory usage
        Query = "SELECT * FROM reportsetting where [your tag if already sent] = false and SendingTime <= [current date and time]  order by SendingTime;";

        MySqlConnection con = new MySqlConnection(conn);
        MySqlCommand comm = new MySqlCommand(Query, con);
        con.Open();
        MySqlDataReader dr = comm.ExecuteReader();
        while (dr.Read())
        {
                //Execute Function and send reports based on the data from the database.

                Thread thread = new Thread(sendReports);
                thread.Start();

                //sleep for half a second before proceeding to the next record if any
                Thread.Sleep(500); 
        }
    }

答案 3 :(得分:1)

或者你可以在新线程中启动它而不使用计时器

var threadStart = new ThreadStart(<your method delegate>);
var thread = new Thread(threadStart);
thread.Start();