• 关于线程


    在开发中经常会遇到线程的例子,如果某个后台操作比较费时间,我们就可以启动一个线程去执行那个费时的操作,同时程序继续执行。在某些情况下可能会出现多个线程的同步协同的问题,下面的例子就展示了在两个线程之间如何协同工作。
    
    这个程序的思路是共同做一件事情(从一个ArrayList中删除元素),如果执行完成了,两个线程都停止执行。
    
    代码如下:
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Threading;
    
    /// <summary>
    /// 在开发中经常会遇到线程的例子,如果某个后台操作比较费时间,我们就可以启动一个线程去执行那个费时的操作,同时程序继续执行。在某些情况下可能会出现多个线程的同步协同的问题,下面的例子就展示了在两个线程之间如何协同工作。
    ///
    ///这个程序的思路是共同做一件事情(从一个ArrayList中删除元素),如果执行完成了,两个线程都停止执行。
    ///作者:周公
    /// 时间:2008-5-17
    /// 原发地址:http://blog.csdn.net/zhoufoxcn
    /// </summary>
    public class ThreadDemo
    {
        private Thread[] threads;
        private int thrs = 5;
        private ArrayList stringList;
        private event EventHandler OnNumberClear;//数据删除完成引发的事件
        public static void Main()
        {
            ThreadDemo demo = new ThreadDemo(100);
            demo.Action();
        }
        public ThreadDemo(int number)
        {
            Random random = new Random(1000000);
            stringList = new ArrayList(number);
            for (int i = 0; i < number; i++)
            {
                stringList.Add(i.ToString());
            }
            threads = new Thread[thrs];
            for (int i = 0; i < thrs; i++)
            {
                threads[i] = new Thread(new ThreadStart(Run));
                threads[i].Name = "线程" + (i + 1);
            }
            OnNumberClear += new EventHandler(ThreadDemo_OnNumberClear);
    
        }
        /// <summary>
        /// 开始工作
        /// </summary>
        public void Action()
        {
            for (int i = 0; i < thrs; i++)
            {
                threads[i].Start();
            }
        }
        /// <summary>
        /// 共同做的工作
        /// </summary>
        private void Run()
        {
            string stringValue = null;
            while (true)
            {
                Monitor.Enter(this);//锁定,保持同步
                stringValue = (string)stringList[0];
                Console.WriteLine(Thread.CurrentThread.Name + "删除了" + stringValue);
                stringList.RemoveAt(0);//删除ArrayList中的元素
                if (stringList.Count == 0)
                {
                    OnNumberClear(this, new EventArgs());//引发完成事件
                }
                Monitor.Exit(this);//取消锁定
                Thread.Sleep(5);
            }
        }
    
        //执行完成之后,停止所有线程
        void ThreadDemo_OnNumberClear(object sender, EventArgs e)
        {
            Console.WriteLine("执行完了,停止了所有线程的执行。");
            for (int i = 0; i < thrs; i++)
            {
                threads[i].Abort();
            }
        }
    }
     

    用例:

    using PMS.DBEntity;
    using System;
    using System.Web;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.IO;
    
    namespace PMS.Convert.PDF
    {
        public struct FileInfo
        {
            public int fileid;
            public string filepath;
        }
    
    
        public class ConvertSwf
        {
            static Queue<FileInfo> filelist = new Queue<FileInfo>();
            private static string rootpath = HttpContext.Current.Server.MapPath("~/");
            private static Thread t = null;
            private static string conn = "";
            public static void LoadQueue(int classid, string _conn)
            {
                conn = _conn;
                using (var entity = new PMSEntities(conn))
                {
                    DALContent dal = new DALContent();
                    var fileinfo = (from p in entity.jcms_normal_content
                                    where p.ClassId == classid && p.IsPass == 1 && p.CustomField05.Substring(0, 10) == "pdf" && p.CustomField03 != null
                                    select p);
    
                    if (!fileinfo.Any())
                    {
                        return;
                    }
                    foreach (var item in fileinfo)
                    {
                        filelist.Enqueue(new FileInfo { fileid = item.Id, filepath = rootpath + "" + item.CustomField03.Remove(0, 1) });
                        item.CustomField05 = "convet";
                    }
                    entity.SaveChanges();
                }
            }
            public static void ExecTreade()
            {
                try
                {
                    if (t == null)
                    {
                        t = new Thread(Run);
                        t.Start();
                    }
                    if (!t.IsAlive)
                    {
                        t = new Thread(Run);
                        t.Start();
                    }
                }
                catch (Exception)
                {
    
                    throw;
                }
    
            }
    
            public static string sourcefile = "";
            static string outfile = "";
            static void Run()
            {
                Pdf2Swf pdf2swf = new Pdf2Swf();
                string saveName = "";
                string extension = "";
                string outfile = "";
                int id = 0;
                using (var entity = new PMSEntities(conn))
                {
                    while (filelist.Count > 0)
                    {
                        FileInfo f = filelist.Dequeue(); ;
                        sourcefile = f.filepath;
                        id = f.fileid;
                        saveName = Path.GetFileName(sourcefile);
                        extension = Path.GetExtension(sourcefile).ToLower();
                        saveName = saveName.Substring(0, saveName.Length - extension.Length);
                        outfile = Path.GetDirectoryName(sourcefile) + "/" + saveName + "_%.swf";
                        try
                        {
                            pdf2swf.PDFConvertToSWF(sourcefile, outfile);
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                            continue;
                        }
                        var content = entity.jcms_normal_content.SingleOrDefault(p => p.Id == id);
                        if (File.Exists(outfile.Replace("_%", "_1")))
                        {
                            content.CustomField04 = "/" + outfile.Replace(rootpath, "").Replace("_%", "_[*,0]");
                            content.CustomField05 = "complete";
                            entity.SaveChanges();
                        }
                        else
                        {
                            content.CustomField04 = "";
                            content.CustomField05 = "error";
                            entity.SaveChanges();
                        }
                    }
                }
                 
                t.Abort();
    
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace MyProject.Common
    {
        public static class TaskUility
        {
            static TaskUility()
            {
                Run();
            }
            /// <summary>
            /// 开启线程
            /// </summary>
            public static void Run()
            {
                taskThread.Start();
            }
            //线程互斥  
            private static readonly object _syncObject = new object();
            //初始化队列  
            private static Queue<Action> taskList = new Queue<Action>();
            //初始化线程
            private static Thread taskThread = new Thread(RunTask);
            public static void Add(Action action)
            {
                lock (_syncObject)
                {
                    // 把任务加入队列中
                    taskList.Enqueue(action);
                }
            }
    
            private static void RunTask()
            {
                while (true)
                {
                Action action = null;
                     
                    lock (_syncObject)
                    {
                        //当队列有数据,出队.
                        if (taskList.Count > 0)
                        {
                            action = taskList.Dequeue();
                            // 执行action
                            if (action != null)
                            {
                                action();
                            }
                        }
                    }
                    Thread.Sleep(5); 
                }
            } 
        }
    }

    现在有100个任务,需要多线程去完成,但是要限定同时并发数量不能超过5个。

    写个简单的类就完成了需求

        public class LimitedTaskFactoryEx
        {
            private readonly int _maxThreadCount = 5;
    
            public LimitedTaskFactoryEx(int maxThreadCount)
            {
                _maxThreadCount = maxThreadCount;
                Start();
            }
    
            private readonly SafedQueue<Action> _actionQueue = new SafedQueue<Action>();
    
            public void StartNew(Action action)
            {
                _actionQueue.Enqueue(action);
            }
    
            private void Start()
            {
                for (int i = 0; i < _maxThreadCount; i++)
                {
                    var thread = new Thread(new ThreadStart(InternalRun));
                    thread.Start();
                }
            }
    
            private void InternalRun()
            {
                while (true)
                {
                    var action = _actionQueue.Dequeue();
                    if (action != null)
                    {
                        action();
                    }
                    else
                    {
                        Thread.Sleep(30);
                    }
                    Console.WriteLine(string.Format("Index: {0}, TaskId: {1}, ThreadId: {2}.", 1, Task.CurrentId,
            Thread.CurrentThread.ManagedThreadId));
                }
            }
        }

    定义个线程池ThreadPool
    然后可以指定最小线程数量和最大线程数量,分别定义成0和5就行了
    然后把方法用线程池执行

        public class MyTaskList
        {
            public List<Action> Tasks = new List<Action>();
     
            public void Start()
            {
                for (var i = 0; i < 5; i++)
                    StartAsync();
            }
     
            public event Action Completed;
     
            public void StartAsync()
            {
                lock (Tasks)
                {
                    if (Tasks.Count > 0)
                    {
                        var t = Tasks[Tasks.Count - 1];
                        Tasks.Remove(t);
                        ThreadPool.QueueUserWorkItem(h =>
                        {
                            t();
                            StartAsync();
                        });
                    }
                    else if (Completed != null)
                        Completed();
                }
            }
        }

    测试

     var rnd = new Random();
                var lst = new MyTaskList();
                for (var i = 0; i < 100; i++)
                {
                    var s = rnd.Next(10);
                    var j = i;
                    var 测试任务 = new Action(() =>
                    {
                        Console.WriteLine(string.Format("第{0}个任务(用时{1}秒)已经开始", j, s));
                        Thread.Sleep(s * 1000);
                        Console.WriteLine(string.Format("第{0}个任务(用时{1}秒)已经结束", j, s));
                    });
                    lst.Tasks.Add(测试任务);
                }
                lst.Completed += () => Console.WriteLine("____________________没有更多的任务了!");
                lst.Start();

    参考文摘:

    如何简易的提高吞吐量 http://www.cnblogs.com/selfteam/p/4912602.html

    C#任务队列的实现代码 http://blog.csdn.net/zwc0910/article/details/8127268  http://blog.csdn.net/tonnychu/article/details/46531001

    多线程调用  ThreadPool.QueueUserWorkItem http://bbs.csdn.net/topics/390819824

    为什么要放弃使用Thread.Sleep  http://www.cnblogs.com/fujet/p/4337392.html?utm_source=tuicool&utm_medium=referral

  • 相关阅读:
    matlab 使用OPENCV
    MATLAB SVM
    RestClient POST
    IIS HTTPS 禁用不安全的SSL2.0
    ping + 时间 日志
    matlab 文件遍历
    matlab 投影
    Oracle创建表空间、创建用户以及授权、查看权限
    php使用<?php include之后页首有空白
    sql点滴40—mysql乱码问题总结
  • 原文地址:https://www.cnblogs.com/shy1766IT/p/5115008.html
Copyright © 2020-2023  润新知