C# Windows服务中的无限while循环

C# Windows服务中的无限while循环,c#,windows-services,infinite-loop,C#,Windows Services,Infinite Loop,我有一个windows,其中我在OnStart()方法中添加了一个无限while循环。我已经测试了该服务1小时,它运行良好。但由于这是我的第一个windows服务,因此对无限循环的性能有疑问。 这是密码 protected override void OnStart(string[] args) { while(true){ string Query=""; Query = "SELECT * FROM 'reportsetting`

我有一个windows,其中我在OnStart()方法中添加了一个无限while循环。我已经测试了该服务1小时,它运行良好。但由于这是我的第一个
windows服务
,因此对无限循环的性能有疑问。 这是密码

 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() { 



    }

所以我想知道从长远来看它是否可以。谢谢..

您几乎肯定不想在无限循环中查询DB。您可能想做的是每隔一段时间(例如,每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);
    }
}

要每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();
        }
    }
}
private const string Query=“SELECT*FROM”reportsetting`按发送时间排序;”
启动时受保护的覆盖无效(字符串[]args)
{
_定时器=新定时器(40*1000);//每40秒
_timer.appeated+=新系统.Timers.ElapsedEventHandler(timer_appeated);
_timer.Start();//试试这个

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); 
        }
    }
bool\u IsStop=false;
启动时受保护的覆盖无效(字符串[]args)
{
base.OnStart(args);
而(!this.\u IsStop)
{
这个过程();
//40秒超时
Thread.Sleep(1000*40);//1000是1秒
}
//如果我们到了这里
//这里打扫一下
}
受保护的覆盖void OnStop()
{
//服务被服务上的用户或操作系统停止
这是正确的;
}
私有无效进程()
{
字符串查询=”;
//-->>>如果在查询中使用类似的内容,并在数据库中使用少量设置
//这将提高内存使用效率

Query=“SELECT*FROM reportsetting,其中[your tag if haven send]=false和SendingTime,或者您可以在新线程中启动它而不使用计时器

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


这听起来是一个非常糟糕的主意,但您对细节描述得不够详细。循环中是否存在中断条件?@JamesCross根据条件,我必须从数据库中不断读取,随后根据条件,我必须在thread@JamesCross我已经用完整的代码更新了我的帖子。请告诉我该公司de效率很低。但要解决您的问题(正确)问题看一下如何使用计时器。当你想再次查询时,让系统每分钟左右给你回一次电话:@JamesCross实际上根据我的条件,我必须每
40秒查询一次
,然后执行代码。是的,只是显示40秒的时间。无论如何,编译器都会为我们排序。没有问题效率低下。@JamesCross我需要花多少时间在
1分钟
。我的意思是我必须为它增加什么价值。是吗。
60*1000
?没错。在10分钟内再花一次
10*60*1000
@JamesCross好的,我还有一个疑问,就像我的
while(dr.Read())
如果
if((str=DateTime.Now.ToString)()HH:mm”).Equals(time))
条件满足后将
Thread-Thread=new-Thread(sendReports);
在后台执行,然后我们将获得下一个
time
值,或者先执行线程,然后执行while(dr)loopy
sendReports
方法将在新线程中运行,但
while(dr.Read())
仍将在与以前相同的线程中运行。是因为我将从数据库中获取新的时间值,而sendReports()将在后台运行。我说得对吗?一旦执行了查询循环,您可以将日期作为从c#或在数据库中计算的条件传递(很抱歉,我对MySQL dateAdd函数不太熟悉)。是的,因为您为sendReport的每条记录生成了线程。抱歉,我没有收到您的消息。我怀疑我的函数
sendReport()
是否会作为线程在后台执行(或者其他我不熟悉的函数,我很抱歉),我将转到
While(dr.Read())
并将获得新的
时间
值,随后新线程将启动当前案例将在后台运行,因为您每次迭代记录都创建一个线程,这意味着它们将独立工作,直到过程完成。这种退避是增量的,而不是指数的。@ssmith ha,确实是-这有点不相关,tbh,was只是想举个例子(不过会更新正确性)。谢谢