zoukankan      html  css  js  c++  java
  • 多线程并发删除日志小工具

    2016年过年后没什么新任务,于是自己做了个定时删除日志的小工具,方便以后的工作中用到,也希望能给大家一点帮助,有不对的地方多多指教。

    功能不是很复杂,主要实现了以下几个功能:

    1.定时检测本地磁盘空间,当空间不足时,做出相应的提醒。

    2.支持动态创建N个磁盘定时删除任务。

    3.支持多线程并发删除操作,避免出现锁死现象。

    4.能够同时支持文件的删除和子文件夹的删除。

    废话不多说,先上具体代码:

    • 删除文件夹里的文件方法
    private bool ToDeleteFile(string url)
            {
                ListViewItem listItem = null;
                if (string.IsNullOrWhiteSpace(url))
                    return false;
                else
                {
                    //遍历文件夹里的所有文件
                    try
                    {
                        fileCount = 0;
                        DirectoryInfo info = new DirectoryInfo(url);
                        foreach (FileInfo file in info.GetFiles())
                        {
                            DateTime lastDate = file.LastWriteTime;//获取文件最后一次写入时间
                            DateTime dtNow = DateTime.Now;
                            TimeSpan ts = dtNow - lastDate;
                            if (sysTie.Enabled == true)
                            {
                                if (ts.Days > int.Parse(DeleteLogDays))
                                {
                                    fileSize += (float.Parse(file.Length.ToString()) / (1024 * 1024));
                                    file.Delete();
                                    fileCount++;
                                }
                            }
                        }
                        listItem = AddListViewData("成功!--删除文件", "删除" + url + "里的日志文件" + fileCount + "个", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        listItem.ForeColor = Color.Blue;
                        if (fileCount > 0)
                        {
                            this.lstMessage.Items.Add(listItem);
                            lbl.Text = fileSize.ToString("F2") + " M";
                        }
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                }
            }
    
    • 删除文件夹里的子文件夹方法

      

    private bool ToDeleteFolder(string url)
            {
                ListViewItem listItem = null;
                if (string.IsNullOrWhiteSpace(url))
                    return false;
                else
                {
                    //遍历文件夹里的所有子文件夹
                    try
                    {
                        fileCount = 0;
                        DirectoryInfo info = new DirectoryInfo(url);
                        foreach (DirectoryInfo floder in info.GetDirectories())
                        {
                            DateTime lastDate = floder.LastWriteTime;//获取文件最后一次写入时间
                            DateTime dtNow = DateTime.Now;
                            TimeSpan ts = dtNow - lastDate;
                            if (sysTie.Enabled == true)
                            {
                                if (ts.Days > int.Parse(DeleteFolderDays))
                                {
                                    fileSize += (float.Parse(GetFloderFileSize(floder.GetFiles()).ToString()) / (1024 * 1024));
                                    floder.Delete(true);
                                    fileCount++;
                                }
                            }
                        }
                        listItem = AddListViewData("成功!--删除子文件夹", "删除" + url + "里的子文件夹" + fileCount + "个", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        listItem.ForeColor = Color.Blue;
                        if (fileCount > 0)
                        {
                            this.lstMessage.Items.Add(listItem);
                            lbl.Text = fileSize.ToString("F2") + " M";
                        }
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                }
            }
    

      下面是定时删除任务:

    • 定时删除文件夹里的文件
    private void StartUpTimerFile(string url)
            {
                ListViewItem listItem = null;
                if (!IsUrlExist(url))
                {
                    listItem = AddListViewData("失败!--启动删除文件", "启动" + url + "路径失败,没有找到对应的文件夹", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    listItem.ForeColor = Color.Red;
                }
                else
                    listItem = AddListViewData("成功!--启动删除文件", "启动删除文件任务成功,已开始运行,路径:" + url, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                this.lstMessage.Items.Add(listItem);
    
                sysTie = new System.Timers.Timer(int.Parse(logTime));
                sysTie.Elapsed += (o, s) =>
                {
                    if (DateTime.Now.Hour == int.Parse(deleteLogTime))
                    {
                        DelegateToDeleteFile del = new DelegateToDeleteFile(ToDeleteFile);
                        BeginInvoke(del, url);
                    }
                };
                sysTie.Start();
            }
    

      

    • 定时删除文件夹里的子文件夹
    private void StartUpTimerFolder(string url)
            {
                ListViewItem listItem = null;
                if (!IsUrlExist(url))
                {
                    listItem = AddListViewData("失败!--启动删除子文件夹", "启动" + url + "路径失败,没有找到对应的文件夹", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    listItem.ForeColor = Color.Red;
                }
                else
                    listItem = AddListViewData("成功!--启动删除子文件夹", "启动删除子文件夹任务成功,已开始运行,路径:" + url, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                this.lstMessage.Items.Add(listItem);
    
                sysTie = new System.Timers.Timer(int.Parse(FolderTime));
                sysTie.Elapsed += (o, s) =>
                {
                    if (DateTime.Now.Hour == int.Parse(DeleteFolderTime))
                    {
                        DelegateToDeleteFile del = new DelegateToDeleteFile(ToDeleteFolder);
                        BeginInvoke(del, url);
                    }
                };
                sysTie.Start();
            }
    

      由于调用方法时,会报异常,所以这块我采用委托来加载上面的方法:

            /// <summary>
            /// 委托开始方法--删除文件
            /// </summary>
            /// <param name="url"></param>
            public void DelegateMethodFile(string url)
            {
                MyDelegateTimer delTimer = new MyDelegateTimer(StartUpTimerFile);
                BeginInvoke(delTimer, url);
            }
    
            /// <summary>
            /// 委托开始方法--删除子文件夹
            /// </summary>
            /// <param name="url"></param>
            public void DelegateMethodFolder(string url)
            {
                MyDelegateTimer delTimer = new MyDelegateTimer(StartUpTimerFolder);
                BeginInvoke(delTimer, url);
            }
    

      以上代码单个删除任务的执行,如何实现多个删除任务的并发运行,因为在我写的时候出现了如果我启动多个删除任务的时候stop()上一个运行的任务,只会运行刚刚启动的任务,所以这块我使用了一个高效的线程安全队列ConcurrentQueue,坚持先进先出的原则。

    • 创建一个可以由多个线程同时访问的键值集合ConcurrentDictionary<string, string>  
    public ConcurrentDictionary<string, string> WriteQueue(string s, string prefix)
            {
                if (string.IsNullOrWhiteSpace(s))
                    return null;
                string val = s;
                string key = prefix;
    
                _logQueue.Enqueue(new KeyValuePair<string, string>(key, val));
                var dic = GetLogText();
                return dic;
            }
    
            /// <summary>
            /// 写入队列操作
            /// </summary>
            /// <returns></returns>
            private ConcurrentDictionary<string, string> GetLogText()
            {
                do
                {
                    KeyValuePair<string, string> kv;
                    if (_logQueue.TryDequeue(out kv))
                    {
                        dict.AddOrUpdate(kv.Key, kv.Value, (k, v) => string.Concat(v + "
    " + kv.Value));
                    }
                }
                while (_logQueue.Count > 0);
                return dict;
            }
    

      下面是启动多线程事件:

    private void button1_Click(object sender, EventArgs e)
            {
                this.lstMessage.Items.Clear();
                dict = new ConcurrentDictionary<string, string>();
                _logQueue = new ConcurrentQueue<KeyValuePair<string, string>>();
                if (strBackList == null || strBackList.Count == 0)
                {
                    MessageBox.Show("路径不能为空,请输入详细地址!");
                    return;
                }
                foreach (KeyValuePair<string, string> obj in strBackList)
                {
                    if (!string.IsNullOrWhiteSpace(obj.Value))
                    {
                        string strKey = obj.Key;
                        string[] s = obj.Value.Split('|');
                        if (s.Length > 0)
                        {
                            foreach (var v in s)
                            {
                                if (!string.IsNullOrWhiteSpace(v))
                                {
                                    dict = WriteQueue(v, string.Format("{0}-{1}", strKey.Substring(0, 1), clickCount.ToString()));
                                    clickCount++;
                                }
                            }
                        }
                    }
                }
                if (dict != null)
                {
                    lock (_lockObject)
                    {
                        foreach (var kv in dict)
                        {
                            if (!string.IsNullOrWhiteSpace(kv.Key))
                            {
                                switch (int.Parse(kv.Key.Substring(0, 1)))
                                {
                                    //All
                                    case 0:
                                        DelegateMethodFile(kv.Value);
                                        DelegateMethodFolder(kv.Value);
                                        break;
                                    case 1://file
                                        DelegateMethodFile(kv.Value);
                                        break;
                                    case 2://folder
                                        DelegateMethodFolder(kv.Value);
                                        break;
                                    default://none
                                        break;
                                }
                            }
                        }
                    }
                }
                this.button1.Enabled = false;
                button1.Text = "任务执行中...";
            }
    

      这样就实现了多线程之间的并发执行,下面是页面效果图

    上面就是我自己这次的总结,只上传了些核心代码,有不对的地方尽请谅解,只是个人的学习记录。

  • 相关阅读:
    树莓派3的无线设置
    Zabbix监控
    使用mutt+msmtp在Linux命令行界面下发邮件(续)
    K8S(16)集成实战-使用spinnaker进行自动化部署
    K8S(15)监控实战-ELK收集K8S内应用日志
    K8S(14)监控实战-grafana出图_alert告警
    K8S(13)监控实战-部署prometheus
    K8S(12)配置中心实战-多环境交付apollo三组件
    K8S(11)配置中心实战-单环境交付apollo三组件
    K8S(10)配置中心实战-configmap资源
  • 原文地址:https://www.cnblogs.com/suzhiyong1988/p/5211902.html
Copyright © 2011-2022 走看看