>

IDE使用教程,四十三十二线程编制程序体系

- 编辑:云顶娱乐yd2221 -

IDE使用教程,四十三十二线程编制程序体系

目录

在我们一直项目中平日会遇见定期任务,比方依期同步数据,按期备份数据,准期计算数据等,定期职分大家都晓得使用Quartz.net,此类别写的也是Quartz,但是早先,大家先用别的方法做个大致的依期义务举办入门。

后日自家希图记录生机勃勃篇关于遍历的博客,因为感觉它是咱们随后专门的学业最常用的风度翩翩种方法了。比方说在叁个模块里插入小Logo,如京东网页右边的小Logo<i></i>。

更新内容,v4.2.2版本:
style="font-size: 16px;">1.充实Modbus合同读取三个寄放器,况兼按七种数据类型分析数据。
2.Modbus Serial和Modbus TCP多少个驱动合併成叁个驱动。
style="font-size: 16px;">3.改善数据库布局,保存配置消息。
style="font-size: 16px;">4.优化ServerSuperIO宗旨代码,应用进程中的潜在难题。

v4.2.2 下载地址:官方下载

目录

  • C#三十二线程编制程序类别(二)- 线程底蕴
    • 1.1 简介
    • 1.2 创设线程
    • 1.3 暂停线程
    • 1.4 线程等待
    • 1.5 终止线程
    • 1.6 检查测量检验线程状态
    • 1.7 线程优先级
    • 1.8 前台线程和后台线程
    • 1.9 向线程传递参数
    • 1.10 C# Lock关键字的施用
    • 1.11 使用Monitor类锁定能源
    • 1.12 多线程中拍卖特别
  • 参照书籍
  • 小编水平有限,倘若不当迎接各位舆情指正!

首先呢,大家今天友好先写三个简约的准时循环职分,话十分少说,直接上代码:

机智图中遍历也是要求的重大用法。


  • 1.1 简介
  • 1.2 实行基本原子操作
  • 1.3 使用Mutex类
  • 1.4 使用SemaphoreSlim类
  • 1.5 使用AutoResetEvent类
  • IDE使用教程,四十三十二线程编制程序体系。1.6 使用ManualResetEventSlim类
  • 1.7 使用CountDownEvent类
  • 1.8 使用Barrier类
  • 1.9 使用ReaderWriterLockSlim类
  • 1.10 使用SpinWait类
  • 参照书籍
  • 小编水平有限,借使不当应接各位商量指正!

C#三十六线程编制程序类别(二)- 线程基本功


第一步:制造项目,新建一个类库:大家命名叫TaskBase

遍历又是循环中最广泛的标题。

 目       录


1.1 简介

线程基本功首要不外乎线程创造、挂起、等待和安息线程。关于更加多的线程的平底完成,CPU时间片轮转等等的知识,能够参照《深入理解计算机系统》大器晚成书中有关进程和线程的章节,本文但是多废话。

其次部:增添二个虚幻功底类BaseMonitor:

所谓遍历,是指有有个别范围的样本数,供给把样品中的每一个数据抽取来大器晚成一解析。

3. Modbus公约,读取多个寄存器,完结四种数据类型深入深入分析... 2


1.2 创制线程

在C#言语中,创立线程是意气风发件特轻松的事务;它只需求用到 System.Threading取名空间,在那之中最首要运用Thread类来创建线程。

身体力行代码如下所示:

using System;
using System.Threading; // 创建线程需要用到的命名空间
namespace Recipe1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1.创建一个线程 PrintNumbers为该线程所需要执行的方法
            Thread t = new Thread(PrintNumbers);
            // 2.启动线程
            t.Start();

            // 主线程也运行PrintNumbers方法,方便对照
            PrintNumbers();
            // 暂停一下
            Console.ReadKey();
        }

        static void PrintNumbers()
        {
            // 使用Thread.CurrentThread.ManagedThreadId 可以获取当前运行线程的唯一标识,通过它来区别线程
            Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 开始打印...");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 打印:{i}");
            }
        }
    }
}

运维结果如下图所示,咱们得以因此运营结果得悉上边的代码创制了叁个线程,然后主线程和创建的线程交叉输出结果,那注明PrintNumbers艺术相同的时间运维在主线程和其它一个线程中。

图片 1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TaskBase
{
    /// <summary>
    /// 监测基础抽象类
    /// </summary>
    public abstract class BaseMonitor
    {

        protected System.Threading.Thread _thread;
        /// <summary>
        /// 监控时间间隔(毫秒)
        /// </summary>
        public virtual int Interval { get; set; }

        public virtual string Name { get; set; }
        /// <summary>
        /// 监控器状态
        /// </summary>
        public virtual TaskState State { get; set; }
        public BaseMonitor(string name)
        {
            Name = name;
            _thread = new System.Threading.Thread(BaseRun);
            _thread.IsBackground = true;//获取或设置一个值,该值指示某个线程是否为后台线程
            _thread.Start();
            State = TaskState.运行;
        }
        private void BaseRun()
        {          
            while (State==TaskState.运行)
            {
                try
                {
                    Run();
                    System.Threading.Thread.Sleep(Interval);
                }
                catch (Exception ex)
                {
                    State = TaskState.异常;
                    PCore.Log.LogTextHelper.WriteErrorLog(this.GetType().Name + "监控出现错误,此监视器已暂停!", ex);
                }
            }
        }
        protected virtual void Run()
        { }
    }
}

诸如,输出100-200里面包车型大巴有着数字,它的范本范围正是100-200,需求您种种把样板中的每叁个数据收取来输出。

3.1           概述... 2

1.1 简介

本章介绍在C#中达成线程同步的两种艺术。因为多个线程同时访问分享数据时,恐怕会以致共享数据的毁坏,进而造成与预期的结果不适合。为了消灭这些标题,所以须求用到线程同步,也被俗称为“加锁”。然则加锁相对不对提升品质,最多也正是不增不减,要完毕质量不增不减还得靠高素质的同步源语(Synchronization Primitive卡塔尔(قطر‎。不过因为不错永恒比速度更关键,所以线程同步在少数场景下是必得的。

线程同步有三种源语(Primitive卡塔尔(英语:State of Qatar)构造:客户形式(user - mode卡塔尔国水源情势(kernel - mode卡塔尔国,当财富可用时间短的情况下,客商方式要优于基本情势,可是只要长日子无法获得能源,或许说长日子处在“自旋”,那么内核方式是相对来讲好的接纳。

可是大家目的在于全数客户情势和根本方式的优点,大家把它称为错落布局(hybrid construct卡塔尔(قطر‎,它装有了二种形式的优点。

在C#中有三种线程同步的体制,常常能够依据以下顺序举办选用。

  1. 若果代码能通过优化能够不开展同盟,那么就绝不做风华正茂道。
  2. 使用原子性的Interlocked方法。
  3. 使用lock/Monitor类。
  4. 应用异步锁,如SemaphoreSlim.WaitAsync()
  5. 选用其余加锁机制,如ReaderWriterLockSlim、Mutex、Semaphore等。
  6. 假定系统提供了*Slim本子的异步对象,那么请接纳它,因为*Slim本子全是混合锁,在进入幼功情势前完毕了某种方式的自旋。

在协作中,必供给当心防止死锁的发出,死锁的爆发必需满足以下4个着力尺度,所以只须要破坏自便一个尺度,就可防止生出死锁。

  1. 排他或互斥(Mutual exclusion卡塔尔(英语:State of Qatar):二个线程(ThreadA卡塔尔(قطر‎独占多少个能源,未有别的线程(ThreadB卡塔尔国能得到相仿的财富。
  2. 占用并等待(Hold and wait卡塔尔国:互斥的一个线程(ThreadA卡塔尔国央浼获取另多少个线程(ThreadB卡塔尔(قطر‎占领的财富.
  3. 不得超越(No preemption卡塔尔:一个线程(ThreadA卡塔尔国据有财富不能够被免强拿走(只可以等待ThreadA主动释放它的能源卡塔尔国。
  4. 巡回等待条件(Circular wait condition卡塔尔(قطر‎:三个或七个线程构成二个巡回等待链,它们锁定七个或七个相似的财富,每种线程都在等待链中的下三个线程占领的能源。

1.3 暂停线程

暂停线程这里运用的艺术是通过Thread.Sleep方式,尽管线程实践Thread.Sleep方法,那么操作系统就要内定的时日内不为该线程分配任曾几何时间片。假诺Sleep时间100ms那么操作系统将起码让该线程睡眠100ms大概更加长日子,所以Thread.Sleep方法不能作为高精度的电火花计时器使用。

示范代码如下所示:

using System;
using System.Threading; // 创建线程需要用到的命名空间
namespace Recipe2
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1.创建一个线程 PrintNumbers为该线程所需要执行的方法
            Thread t = new Thread(PrintNumbersWithDelay);
            // 2.启动线程
            t.Start();

            // 暂停一下
            Console.ReadKey();
        }

        static void PrintNumbersWithDelay()
        {
            Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 开始打印... 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}");
            for (int i = 0; i < 10; i++)
            {
                //3. 使用Thread.Sleep方法来使当前线程睡眠,TimeSpan.FromSeconds(2)表示时间为 2秒
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 打印:{i} 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}");
            }
        }
    }
}

运营结果如下图所示,通过下图能够规定上边的代码是立见成效的,通过Thread.Sleep主意,使线程休眠了2秒左右,不过并非非常确切的2秒。验证了上边包车型大巴说教,它的上床是最少让线程睡眠多久,并不是早晚多长期。

图片 2

(代码中PCore.Log.LogTextHelper.WriteErrorLog 是叁个写文本日志的章程,可活动写个此措施。)

再比如,将50-70里边的具有数字相加求和,它的范本范围正是50-70,须要你各样把样品中的每三个数据抽取来累计。

3.2           Modbus根基知识... 2

1.2 施行基本原子操作

CLEvoque保险了对这一个数据类型的读写是原子性的:Boolean、Char、(S)Byte、(U)Int16、(U)Int32、(U)IntPtr和Single。不过如果读写Int64也许会时有产生读取撕裂(torn read卡塔尔的主题素材,因为在三十八人操作系统中,它必要进行若干遍Mov操作,不能够在八个岁月内实行到位。

这就是说在本节中,就能够重视的介绍System.Threading.Interlocked类提供的点子,Interlocked类中的每种方法都是实践三回的读取以致写入操作。越来越多与Interlocked类相关的素材请参照他事他说加以调查链接,戳一戳.aspx)本文不在赘述。

亲自去做代码如下所示,分别选择了三种办法打开计数:错误计数方式、lock锁格局和Interlocked原子情势。

private static void Main(string[] args)
{
    Console.WriteLine("错误的计数");

    var c = new Counter();
    Execute(c);

    Console.WriteLine("--------------------------");


    Console.WriteLine("正确的计数 - 有锁");

    var c2 = new CounterWithLock();
    Execute(c2);

    Console.WriteLine("--------------------------");


    Console.WriteLine("正确的计数 - 无锁");

    var c3 = new CounterNoLock();
    Execute(c3);

    Console.ReadLine();
}

static void Execute(CounterBase c)
{
    // 统计耗时
    var sw = new Stopwatch();
    sw.Start();

    var t1 = new Thread(() => TestCounter(c));
    var t2 = new Thread(() => TestCounter(c));
    var t3 = new Thread(() => TestCounter(c));
    t1.Start();
    t2.Start();
    t3.Start();
    t1.Join();
    t2.Join();
    t3.Join();

    sw.Stop();
    Console.WriteLine($"Total count: {c.Count} Time:{sw.ElapsedMilliseconds} ms");
}

static void TestCounter(CounterBase c)
{
    for (int i = 0; i < 100000; i++)
    {
        c.Increment();
        c.Decrement();
    }
}

class Counter : CounterBase
{
    public override void Increment()
    {
        _count++;
    }

    public override void Decrement()
    {
        _count--;
    }
}

class CounterNoLock : CounterBase
{
    public override void Increment()
    {
        // 使用Interlocked执行原子操作
        Interlocked.Increment(ref _count);
    }

    public override void Decrement()
    {
        Interlocked.Decrement(ref _count);
    }
}

class CounterWithLock : CounterBase
{
    private readonly object _syncRoot = new Object();

    public override void Increment()
    {
        // 使用Lock关键字 锁定私有变量
        lock (_syncRoot)
        {
            // 同步块
            Count++;
        }
    }

    public override void Decrement()
    {
        lock (_syncRoot)
        {
            Count--;
        }
    }
}


abstract class CounterBase
{
    protected int _count;

    public int Count
    {
        get
        {
            return _count;
        }
        set
        {
            _count = value;
        }
    }

    public abstract void Increment();

    public abstract void Decrement();
}

运作结果如下所示,与预期结果基本切合。

图片 3

本文由云顶娱乐yd2221发布,转载请注明来源:IDE使用教程,四十三十二线程编制程序体系