zoukankan      html  css  js  c++  java
  • c#定时器Timer

    C# Timer用法有哪些呢?我们在使用C# Timer时都会有自己的一些总结,那么这里向你介绍3种方法,希望对你了解和学习C# Timer使用的方法有所帮助。

    关于C# Timer类  在C#里关于定时器类就有3个

    C# Timer使用的方法1.定义在System.Windows.Forms里

    C# Timer使用的方法2.定义在System.Threading.Timer类里  "

    C# Timer使用的方法3.定义在System.Timers.Timer类里

    下面我们来具体看看这3种C# Timer用法的解释:

    ◆System.Windows.Forms.Timer

    应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或Delphi中的Timer控件,内部使用API  SetTimer实现的。它的主要缺点是计时不精确,而且必须有消息循环,Console  Application(控制台应用程序)无法使用。  

    ◆System.Timers.Timer

    和System.Threading.Timer非常类似,它们是通过.NET  Thread  Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求。

    ◆System.Timers.Timer还可以应用于WinForm,完全取代上面的Timer控件。它们的缺点是不支持直接的拖放,需要手工编码。

                //实例化Timer类,设置间隔时间为10000毫秒; 
                System.Timers.Timer t = new System.Timers.Timer(1000);
    
                //到达时间的时候执行注册事件
                t.Elapsed += (obj,e) => {
                    Console.WriteLine("ok");
                };
    
                //设置是执行一次(false)还是一直执行(true); 
                t.AutoReset = true;
    
                //是否执行System.Timers.Timer.Elapsed注册事件;   
                t.Enabled = true;
                Console.ReadKey();

    javascript 对应的

    setInterval(funciont(){xxxxx},1000)一直执行

    setTimeout(function(){xxxxx},1000)只执行一次

    需求:规定时间启动定时器(比如早上下午6点启动,上午就管理员运行程序 )

    code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Threading;
    
    namespace CsDemo
    {
        class Program
        {
            static System.Timers.Timer t = null;
            static Thread td = null;
            static bool isOpenTimers = false;
            static bool isThreadFalg = true;
    
            static void Main(string[] args)
            {
                Timers(statrDay() * msecTime);//statrDay() * msecTime读取配置文件或者指定时间
    
                Threads();
            }
    
            private static void Threads()
            {
                td = new Thread(ThreadMethod);
                td.IsBackground = true;
                td.Start(td);
            }
    
    
            /// <summary>定时器
            /// </summary>
            public static void Timers(double Time)
            {
                t = new System.Timers.Timer(Time);
                t.Elapsed += (obj, e) =>
                {
                    //Do something
                };
                t.AutoReset = true;
                t.Enabled = true;
            }
    
    
    
            /// <summary>线程 指定时间启动定时器
            /// </summary>
            private static void ThreadMethod(object td)
            {
                var temp = td as Thread;
                while (isThreadFalg)
                {
                    int hour = DateTime.Now.Hour;
                    if (hour >= hourTime)//hourTime 读取配置文件 下午6点
                    {
                        if (!isOpenTimers)
                        {
                            t.Start();
                            Thread.Sleep(1000);
                            temp.Abort();
                        }
                    }
                    Thread.Sleep(300000);
                }
            }
        }
    }

    2:问题 定时器里面方法没有执行完 下一次又启动了 但是我希望排队的方式运行 (上次任务结束才开始)

    code:

            /// <summary>定时器
            /// </summary>
            public static void Timers(double Time)
            {
                t = new System.Timers.Timer(Time);
                t.Elapsed += (obj, e) =>
                {
                    t.Stop();
                    //Do something
                    t.Start();
                };
                t.AutoReset = true;
                t.Enabled = true;
                t.Start();
            }

    3:需求3 假设定时器7天运行一次 1号开启 突然bug或者意外3号天挂了  第4天开启 这个时候  7号继续执行 不能等到4+7 11号执行

    原理:

    每次运行定时器动态计算时间:异常时候写入奔溃时间

    1:

       Timers(statrDay() * msecTime);//mescTime 为 86400000 一天 这样项目原因不考虑
    public double statrDay() { DateTime lastDay = DateTime.Parse(nextDayStar); TimeSpan ts = lastDay - DateTime.Now; var dayTemp = ts.Days; if (dayTemp >= pushTime || dayTemp <= 0) dayTemp = pushTime; return dayTemp; }

    2:Timer Elapsed方法每次运行写入下次启动时间

    Logging.GetInstance().InsertNextDayStart(DateTime.Now.AddDays(pushTime).ToString());pushTime=7 

    3:程序奔溃写入下次启动时间

      public static void InsertLog()
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    while (true)
                    {
                        try
                        {
                            if (tempLog.Count > 0)
                            {
                                string errorMsg = tempLog.Dequeue();
                                Logging.GetInstance().WriteLog(errorMsg, path);
                                Logging.GetInstance().InsertNextDayStart(DateTime.Now.AddDays(frm.pushTime).ToString());
                                Thread.Sleep(30);
                            }
                            else
                            {
                                Thread.Sleep(30000);
                            }
                        }
                        catch (Exception ex)
                        {
                            tempLog.Enqueue("系统错误" + GetExceptionMsg(ex as Exception, ex.ToString()));
                        }
                    }
                });
            }

    为队列 public static Queue<string> tempLog = new Queue<string>();

    详细代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using DAL;
    using Redslide.HttpLib;
    using System.Web;
    using System.Threading;
    using System.Collections.Concurrent;
    using System.Reflection;
    using System.Threading.Tasks;
    using Tool.Entity;
    using System.Diagnostics;
    using System.Configuration;
    using System.IO;
    using System.Web.Script.Serialization;
    
    
    namespace IllegalMsgPush
    {
        public partial class frWz : Form
        {
            #region 全局变量
            System.Timers.Timer t = null;
            Thread td = null;
            bool isOpenTimers = false;
            bool isThreadFalg = true;
          
            string urlCopy = null; 
            ConcurrentDictionary<string, userList> dicUser=null;
            static Task tk = null;
    
            /// <summary>
            /// 违章消息推送时间启动(单位小时)
            /// </summary>
            public int hourTime = 0;
    
            /// <summary>
            /// 违章消息推送定时推送(单位天)
            /// </summary>
            public int pushTime = 0;
    
            /// <summary>
            /// 下次启动时间(day)
            /// </summary>
            public string nextDayStar =null;
    
            Action<string> acCarMsgShow = null;
    
            public int holdID;
            public int msecTime;
    
            /// <summary>同步锁用于删除队列信息与添加消息
            /// </summary>
            private static object _objfrWzMsgLock = new object();
            #endregion
    
            public frWz()
            {
                InitializeComponent();
    
                this.SizeChanged += (o, e) =>
                {
                    if (this.WindowState == FormWindowState.Minimized)
                    {
                        this.Hide();
                        this.notifyIcon1.Visible = true;
                    }
                };
    
                InitializationParameter();
    
                Timers(statrDay() * msecTime);
    
                Threads();
            }
    
            #region      -sql command
    
            /// <summary>用户以及子用户下面的车
            /// </summary>
            private DataTable LoadCarChildList()
            {
                var sql = string.Format(@"with cte as
                                          (
                                            select userName ,userID from std_UserInfo where isDeleted=0
                                          ) 
                                          select a.ObjectID,a.vehicleNum,d.EngineCode,d.ShelfCode ,c.userName
                                                  from dbo.Table_F_GetObjectInfoByObjUserHoldID(0,1,1) a 
                                                  left join std_ObjAppend d with (nolock) on  a.ObjectID=d.ObjectID 
                                                  left join std_UserObj   b with (nolock)  on  d.ObjectID=b.ObjectID 
                                                  left hash join cte c on  b.userID=c.userID 
                                          where c.userName is not null", holdID);
                return SqlHelper.ExecuteDataset(sql).Tables[0];
            }
    
            public void InsertPushInfo(string objectID, string vehclieNum, string userName)
            {
                Task.WaitAll(tk);
                StringBuilder sql = new StringBuilder();
                var temp = objectID + "_" + userName;
                if (ContainsKey(temp))
                {
                    sql.Append(@"INSERT INTO personal_PushInfo
                                                       (Contype,context,UserName,OBDTerminalNo ,voiceName             
                                                        ,isDeleted ,RcvTime ,TypeID ,ID ,VehicleNum
                                                        ,ItemID,voiceDetail,GPSTime ,CerFileName
                                                        ,CerPassword,PushServerType)
                                          ");
                    sql.AppendFormat(@"VALUES('违章','您有一条新的违章消息','{0}','{1}','109.wav'
                                           ,0,getdate(),2,'{2}','{3}'
                                           ,109,'您有一条新的违章消息',getdate(),'{4}'
                                           ,'{5}',1)"
                                              , dicUser[temp].UserName              //UserName
                                              , dicUser[temp].OBDTerminalNo         //OBDTerminalNo
                                              , int.Parse(objectID)                 //ID  -车辆ID ObjectID
                                              , vehclieNum                          //VehicleNum
                                              , dicUser[temp].CerFileName           //CerFileName 安卓null 
                                              , dicUser[temp].CerPassword           //CerPassword 
                                              );
                    SqlHelper.ExecuteNonQuery(sql.ToString());
                }
                else
                {
                    string str = "key不存在异常出现在ID: " + objectID + "车牌:" + vehclieNum + "userName:" + userName;
                    Logging.GetInstance().WriteLog(str, Program.carListLog);
                }
            }
    
            public void LoadUserList()
            {
                dicUser = new ConcurrentDictionary<string, userList>();
                tk = Task.Factory.StartNew(() =>
                {
                    var sql = "SELECT UserName,OBDTerminalNo,ObjectID,CerFileName,CerPassword  FROM std_UserObj  a left hash join std_UserInfo b on a.UserID=b.UserID WHERE b.isDeleted=0";
                    var temp = SqlHelper.ExecuteDataset(sql).Tables[0];
                    if (temp != null || temp.Rows.Count > 0)
                    {
                        var dataType = typeof(userList);
                        var infos = dataType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                        foreach (DataRow row in temp.Rows.AsParallel())
                        {
                            var obj = (userList)Activator.CreateInstance(dataType);
                            foreach (DataColumn col in temp.Columns.AsParallel())
                            {
                                try
                                {
                                    foreach (PropertyInfo info in infos)
                                    {
                                        if (info.Name.ToLower() == col.ColumnName.ToLower())
                                        {
                                            if (row[col].GetType().FullName != "System.DBNull")
                                            {
                                                info.FastSetValue(obj, row[col]);
                                            }
                                        }
                                    }
                                }
                                catch
                                {
                                }
                            }
                            Add(obj.ObjectID.ToString() + "_" + obj.UserName, obj);
                        }
                    }
                });
            }
    
            public void csDemo()
            {
                if (this.txtContent.InvokeRequired)
                {
                    this.txtContent.Invoke(acCarMsgShow, "执行一次");
                }
                string str = @"INSERT INTO personal_PushInfo(Contype,context,UserName,OBDTerminalNo ,voiceName
                                                            ,isDeleted ,RcvTime ,TypeID ,ID ,VehicleNum
                                                            ,ItemID ,voiceDetail,GPSTime ,CerFileName
                                                            ,CerPassword,PushServerType)
                                                     VALUES('报警','车辆设防','chen','d3e0d773cd1dde1a939bde8b4ea5605ffb0a9aa3dd07be1dbb8213f6f7b64862','79.wav'
                                                            ,0,getdate(),1,73252,'粤Blyq'
                                                            , 79,'您有一条新的违章消息',getdate(),'carGeniusP_erp_dev.pem'
                                                            ,'123456',0)";
                SqlHelper.ExecuteNonQuery(str);
            }
            #endregion
    
            private void HttpGet()
            {
                var dt = LoadCarChildList();
                if (dt == null || dt.Rows.Count == 0) return;
                JavaScriptSerializer js = new JavaScriptSerializer();
                foreach (DataRow item in dt.Rows)
                {
                    lock (_objfrWzMsgLock)
                    {
                        var carCode = item["EngineCode"].ToString();
                        if (string.IsNullOrEmpty(carCode)) continue;
                        var carNumber = item["ShelfCode"].ToString();
                        if (string.IsNullOrEmpty(carNumber)) continue;
                        var objectID = item["ObjectID"].ToString();
                        var vehclieNum = item["vehicleNum"].ToString();
                        var userName = item["userName"].ToString();
                        string url = string.Format(urlCopy, HttpUtility.UrlEncode(vehclieNum, System.Text.Encoding.UTF8), GetLastStr(carCode, 6), GetLastStr(carNumber, 6));
                        Request.Get(url, null, result =>
                        {
                            var json = (Dictionary<string, object>)js.DeserializeObject(result);
                            if (json == null) return;
                            if (bool.Parse(json["Success"].ToString()) && bool.Parse(json["HasData"].ToString()))
                            {
                                var tempMsg = "车牌ID:" + objectID  + "--车牌号:" + vehclieNum + "--用户名:" + userName;
                                if (this.txtContent.InvokeRequired) this.txtContent.Invoke(acCarMsgShow, tempMsg);
                                InsertPushInfo(objectID, vehclieNum, userName);
                                Logging.GetInstance().WriteLog(tempMsg, Program.carListLog);
                            }
                            else {
                                Logging.GetInstance().WriteLog(result.ToString(), Program.carListLog);
                            }
                        }, e =>
                        {
                            string str = "http请求错误" + Program.GetExceptionMsg(e, string.Empty);
                            Logging.GetInstance().WriteLog(str, Program.carListLog);
                        });
                    }
                }
            }
    
            #region    event
            private void button1_Click(object sender, EventArgs e)
            {
                if (MessageBox.Show("要重新启动嘛?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    t = null;
                    td = null;
                    notifyIcon1 = null;
                    Application.Restart();
                }
            }
    
            private void frWz__Shown(object sender, EventArgs e)
            {
                this.Visible = true;
                notifyIcon1.Visible = true;
                notifyIcon1.Icon = this.Icon;
            }
    
            private void frWz_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (notifyIcon1 != null)
                {
                    e.Cancel = true;
                    this.Visible = false;
                }
            }
    
            private void ToolStripMenuItem_Show_Click(object sender, EventArgs e)
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
            }
    
            private void ToolStripMenuItem_Exit_Click(object sender, EventArgs e)
            {
                if (MessageBox.Show("你确定退出吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    t = null;
                    td = null;
                    dicUser = null;
                    notifyIcon1 = null;
                    this.Close();
                }
            }
    
            private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Left)
                {
                    notifyIcon1.Visible = true;
                    this.Show();
                    this.WindowState = FormWindowState.Normal;
                }
                else
                {
                    Point pt = new Point();
                    pt = Control.MousePosition;
                    contextMenuStrip1.Show(pt);
                }
            }
            #endregion
    
            private void Threads()
            {
                td = new Thread(ThreadMethod);
                td.IsBackground = true;
                td.Start(td);
            }
    
            /// <summary>定时器
            /// </summary>
            public void Timers(double Time)
            {
                t = new System.Timers.Timer(Time);
                t.Elapsed += (obj, e) =>
                {
                    t.Stop();
                    Logging.GetInstance().InsertNextDayStart(DateTime.Now.AddDays(pushTime).ToString());
                    isOpenTimers = true;
                    LoadUserList();
                    HttpGet();
                    t.Interval = pushTime * msecTime;
                    t.Start();
                };
                t.AutoReset = true;
                t.Enabled = true;
            }
    
            /// <summary>初始化参数和变量
            /// </summary>
            private void InitializationParameter()
            {
                Logging.GetInstance().CreateFile(Program.path, Program.carListLog);
                urlCopy = ConfigRead.GetInstance().pushUrlValue();
                hourTime = ConfigRead.GetInstance().hourTimeValue();
                pushTime = ConfigRead.GetInstance().pushDayValue();
                nextDayStar = Logging.GetInstance().ReadNextDayStart();
                holdID = ConfigRead.GetInstance().holdIDValue();
                msecTime = ConfigRead.GetInstance().msecTimeValue();
                acCarMsgShow = (strMsg) =>
                {
                    txtContent.AppendText("请求成功消息:" + strMsg + "\r\n");
                };
            }
    
            /// <summary>线程 指定时间启动定时器
            /// </summary>
            private void ThreadMethod(object td)
            {
                var temp = td as Thread;
                while (isThreadFalg)
                {
                    int hour = DateTime.Now.Hour;
                    if (hour >= hourTime)
                    {
                        if (!isOpenTimers)
                        {
                            t.Start();
                            Thread.Sleep(1000);
                            temp.Abort();
                        }
                    }
                    Thread.Sleep(300000);
                }
            }
    
            #region IDictionary<string,ResultType> 成员
    
            public void Add(string key, userList value)
            {
                dicUser.TryAdd(key, value);
            }
    
            public bool ContainsKey(string key)
            {
                return dicUser.ContainsKey(key);
            }
    
            public ICollection<string> Keys
            {
                get { return dicUser.Keys; }
            }
    
            public bool Remove(string key)
            {
                userList val;
                return dicUser.TryRemove(key, out val);
            }
    
            public bool TryGetValue(string key, out userList value)
            {
                return dicUser.TryGetValue(key, out value);
            }
    
            public ICollection<userList> Values
            {
                get { return dicUser.Values; }
            }
    
            public userList this[string key]
            {
                get
                {
                    return dicUser[key];
                }
                set
                {
                    dicUser[key] = value;
                }
            }
    
            #endregion
    
            public void updateConfig(string key, string value)
            {
                var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                if (config.AppSettings.Settings[key] != null)
                {
                    config.AppSettings.Settings[key].Value = value;
                }
                else
                {
                    config.AppSettings.Settings.Add(key, value);
                }
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
    
            public double statrDay()
            {
                DateTime lastDay = DateTime.Parse(nextDayStar);
                TimeSpan ts = lastDay - DateTime.Now;
                var dayTemp = ts.Days;
                if (dayTemp >= pushTime || dayTemp <= 0) dayTemp = pushTime;
                return dayTemp; 
            }
    
            public string GetLastStr(string str, int num)
            {
                if (str.Length > num)
                {
                    str = str.Substring(str.Length - num, num);
                }
                return str;
            }
        }
    
        public class userList
        {
            public string UserName { get; set; }
            public string OBDTerminalNo { get; set; }
            public int ObjectID { get; set; }
            public string CerPassword { get; set; }
            public string CerFileName { get; set; }
    
        }
    }
    View Code

    Program

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    using System.Text;
    using Tool.Entity;
    using System.Diagnostics;
    using System.Threading;
    using System.IO;
    using System.Collections;
    
    namespace IllegalMsgPush
    {
        static class Program
        {
            public static frWz frm = null;
            public static string path = "";
            public static string carListLog = "";
            public static Queue<string> tempLog = new Queue<string>();
    
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                #region 应用程序的主入口点
                try
                {
                    bool flag;
                    Mutex mutex = new Mutex(true, Application.ProductName, out flag);
                    if (flag)
                    {
                        path = string.Format("{0}{1}", AppDomain.CurrentDomain.BaseDirectory, @"/log/");
                        carListLog = string.Format("{0}{1}", AppDomain.CurrentDomain.BaseDirectory, @"/carListLog/");
    
                        InsertLog();
    
                        //设置应用程序处理异常方式:ThreadException处理
                        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                        //处理UI线程异常
                        Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                        //处理非UI线程异常
                        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    
                        Application.EnableVisualStyles();
                        Application.SetCompatibleTextRenderingDefault(false);
    
                        frm = new frWz();
    
                        Application.Run(frm);
    
                        //释放 System.Threading.Mutex 一次
                        mutex.ReleaseMutex();
                    }
                    else
                    {
                        MessageBox.Show(null, "相同的程序已经在运行了,请不要同时运行多个程序!\n\n这个程序即将退出!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        Application.Exit();
                    }
                }
                catch (Exception ex)
                {
                    string str = "系统错误" + GetExceptionMsg(ex, string.Empty);
                    tempLog.Enqueue(str);
                }
                #endregion
            }
    
            static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
            {
                string str = "系统错误" + GetExceptionMsg(e.Exception, e.ToString());
                tempLog.Enqueue(str);
            }
    
            static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
            {
                string str = "系统错误" + GetExceptionMsg(e.ExceptionObject as Exception, e.ToString());
                tempLog.Enqueue(str);
            }
    
            public static string GetExceptionMsg(Exception ex, string backStr)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("****************************异常文本****************************");
                sb.AppendLine("【出现时间】:" + DateTime.Now.ToString());
                if (ex != null)
                {
                    sb.AppendLine("【异常类型】:" + ex.GetType().Name);
                    sb.AppendLine("【异常信息】:" + ex.Message);
                    sb.AppendLine("【堆栈调用】:" + ex.StackTrace);
                }
                else
                {
                    sb.AppendLine("【未处理异常】:" + backStr);
                }
                sb.AppendLine("***************************************************************");
                return sb.ToString();
            }
    
            public static void InsertLog()
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    while (true)
                    {
                        try
                        {
                            if (tempLog.Count > 0)
                            {
                                string errorMsg = tempLog.Dequeue();
                                Logging.GetInstance().WriteLog(errorMsg, path);
                                Logging.GetInstance().InsertNextDayStart(DateTime.Now.AddDays(frm.pushTime).ToString());
                                Thread.Sleep(30);
                            }
                            else
                            {
                                Thread.Sleep(30000);
                            }
                        }
                        catch (Exception ex)
                        {
                            tempLog.Enqueue("系统错误" + GetExceptionMsg(ex as Exception, ex.ToString()));
                        }
                    }
                });
            }
        }
    }
    View Code

    配置文件:

    <?xml version="1.0"?>
    <configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
        <appSettings>
            <!--路精灵所属单位ID配置 start-->
            <add key="holdID" value="1"/>
            <!--路精灵所属单位ID配置end-->
    
            <!--违章消息推送时间天数start (正整数)-->
            <add key="pushDay" value="14"/>
            <!--违章消息推送时间天数end (正整数)-->
            
            <!--违章消息推送几点启动start (正整数0-24)-->
            <add key="hourTime" value="6"/>
            <!--违章消息推送几点启动结束end (正整数)-->
            
            <!--违章消息URL start-->
            <add key="pushUrl" value="xxxx"/>
            <!--违章消息URL end-->
    
            <!--违章消息推送毫秒 (默认86400000 测试可调整修改)-->
            <add key="msecTime" value="86400000"/>
            <!--违章消息推送毫秒end (正整数)-->
        </appSettings>
        <connectionStrings>
            <!--数据库连接串开始-->
            <add name="ConnStr" connectionString="xxxxx"/>
            <!--数据库连接串结束-->        
        </connectionStrings>
    </configuration>
    View Code
  • 相关阅读:
    【高端黑】软件工程师去理发店
    [SQL]用于提取组内最新数据,左连接,内连接,not exist三种方案中,到底谁最快?
    Oracle数据库访问客户端 sqldeveloper-19.2.1.247.2212-x64 下载
    《木兰辞》中最精彩的六句
    SqlComparison
    别让情绪扰乱心绪
    50年内神秘消失的恒星
    java命名总结
    针对nginx,来具体聊聊正向代理与反向代理 (转载)
    Nginx可以做什么?(转载)
  • 原文地址:https://www.cnblogs.com/y112102/p/3121615.html
Copyright © 2011-2022 走看看