System.Threading.Timer中的方法

时间:2017-09-25 17:39:51

标签: c# asp.net .net multithreading timer

我在Web服务器应用程序中有一个方法,它在后台每x分钟运行一些mysql查询,我搜索了一个很好的方法来实现它,并遇到了System.Threading.Timer类。我设法在里面编写方法并使用日志我跟踪它的执行情况(每个查询和每个例外)但我面临一个问题,我仍然无法理解什么'发生的事情是,当方法需要实际执行某些操作时(当我在我的应用程序上有一个新记录时,该方法将获取它的数据并开始将其写入我的数据库,但只有在那个时才会这样做x分钟它运行数据,否则它将只运行什么都没有)它停止,查询或线程没有异常,我只是检查日志,在x分钟它应该写上它的东西有什么都没有,一些东西只是杀了我的线程,我无法理解为什么/为什么,如果有人可以帮助我,我会赞赏(抱歉我的英语不好),这里是代码片段:

 using (StreamWriter sw = File.AppendText(path + @"\log_test.txt")) {
                sw.WriteLineAsync("-------- LOG BEGIN --------" + Environment.NewLine);
                try {
                    var timer = new System.Threading.Timer(async (ev) => {
                        bool sync = await AzureSync.Begin();
                    }, null, TimeSpan.Zero, TimeSpan.FromMinutes(2));
                }
                catch (Exception ex) {
                    sw.WriteLine(DateTime.Now + "**** ERROR ****" + Environment.NewLine);
                    sw.WriteLine(ex.ToString() + Environment.NewLine);
                    throw ex;
                }
            }

2 个答案:

答案 0 :(得分:2)

using语句将过快关闭StreamWriter。事实上,它会在设置新计时器后立即关闭StreamWriter。

因此,当计时器以这种方式编码时,计时器无法写入日志。

您需要将设置using的{​​{1}}语句移动到计时器执行的自治方法中。

这对你来说应该更好。

sw

同样在设置计时器时,我不确定TimeSpan.FromMinutes(2)是否适合您。我相信基于这个代码示例:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/threading/thread-timers最后一个参数是以毫秒为单位。所以120000就是你要找的。

需要考虑的其他事项
虽然上面的代码将会工作"它遭受了@Mukesh在他的回答/建议中躲过的严重问题。如果后台进程抛出异常,它将关闭IIS应用程序池进程并强制Web应用程序进行回收。这几乎是不可取的。上面编写代码的方式是,定时器proc中的任何异常都会导致发生这种情况,因为在捕获异常并记录它们之后,它会重新抛出它们。应该认真考虑使用他的回答/建议中提到的第三方后台调度程序,或者至少可以确保没有异常从定时器进程中逃脱:

 var timer = new System.Threading.Timer(async (ev) => {

     using (StreamWriter sw = File.AppendText(path + @"\log_test.txt")) {
           sw.WriteLineAsync("-------- LOG BEGIN --------" + Environment.NewLine);
            try {
                bool sync = await AzureSync.Begin();
            }
            catch (Exception ex) {
                sw.WriteLine(DateTime.Now + "**** ERROR ****" + Environment.NewLine);
                sw.WriteLine(ex.ToString() + Environment.NewLine);
                throw ex;
            }
        }
 }, null, TimeSpan.Zero, 120000);   //120000 milliseconds is 2 Minutes

答案 1 :(得分:1)

我只是给你一个建议:)。 您不应该在Web应用程序中执行后台作业,在IIS Web服务器中,应用程序可能会进入睡眠模式或在工作进程回收期间,您的后台任务将无法执行。除此之外,您可以专门集成库构建以实现后台作业,例如HangfireFLUENTSCHEDULER等,它们也具有非常好的仪表板功能。

请参阅以下有关此事的精彩文章。 How to run Background Tasks in ASP.NET