必赢网上注册-亚洲必赢官方登录

其三方Wechat平台,八线程编制程序种类

日期:2019-12-08编辑作者:必赢网上注册

本篇文章主要介绍泛型的采纳。

    对Google瓦片地图举办更改,有三种方式:一是对拼接大图举行改良,然后再一次切成丝;二是一贯对瓦片图进行改过。这里自个儿用的是第两种形式,即直接对瓦片地图实行修改。

目录

目录

升讯威Wechat营销体系(Wechat第三方平台)

泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提升代码的可重用性、类型安全性和频率。

App.config配置:

  • 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 八线程中管理极其
  • 仿效书籍
  • 小编水平有限,假使不当接待各位争辨指正!
  • 骨干尺度
  • 类设计指南
  • 质量成员安排指南
  • 其余安排指南
  • 可维护性指南
  • 取名指南
  • 脾气指南
  • 框架指南
  • 文书档案指南
  • 结构指南
  • 连锁链接

在线体验:
开源地址GitHub
作者:曹旭升 sheng.chao   

泛型的定义

图片 1图片 2

C#八十八线程编制程序连串(二)- 线程底蕴



证实:有标题上QQ群沟通

下边定义了三个普通类和多个泛型类,大家能够明显看见泛型类和平常类最大的界别便是多了三个<T>。

<appSettings>
  <add key="inputPath" value="D:_临时文件GISMap1818940751"/>
  <add key="outputPath" value="D:_临时文件GISMapOutput1818940751"/>
  <add key="deltaPixcelX" value="1031"/>
  <add key="deltaPixcelY" value="421"/>
  <add key="fromMapZoom" value="1"/>
  <add key="toMapZoom" value="18"/>
</appSettings>

1.1 简介

线程底工主要包涵线程创设、挂起、等待和终止线程。关于越多的线程的最底层完成,CPU时间片轮转等等的文化,能够参见《深入理解计算机系统》生机勃勃书中关于进程和线程的章节,本文然而多废话。

C# 编制程序指南

QQ群:173459027   591928344

故而,这一个<T>就标记了,这些类是泛型类。当中这几个T,也足以写成A,B,C,D或其余字符。

View Code

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措施同期运维在主线程和其余四个线程中。

图片 3

今天在 Github 上见到了一人大咖创立二个商旅:CSharpCodingGuidelines,张开之后看了一下 readme.md 相关描述,感觉应该很科学,于是就 clone 到本地拜读一下,这里列一些和好的笔记,方便日后回首。

笔者最先的梦想是兑现一个Wechat云平台,相近于微盟,只必要商家扫码绑定就可以提供任何的经营出卖效果与利益。
本人的定势是专程服务于线下厂家,举例电影院、商业中央、各样线下门店等,线下厂商的大器晚成部分事务场景和业务流程是比较非常的,和纯现上的万众号营业不尽形似。 那是小编最先想找到的切入点,在系统初始上线后,自身也试着做了推广,富含百度尊敬词、线下陌拜都品尝过,这么些细节有机缘小编会再详尽说一说。

public class Generic
{
    public String Name;
}

public class Generic<T>
{
    public T Name;
}

对瓦片图实行改良处理的算法代码:

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秒。验证了上边的说法,它的睡觉是起码让线程睡眠多久,并不是迟早多久。

图片 4

骨干条件

  • Astonishment 原则:你的代码应该尽量做到让每一位都能驾驭。任哪个人都有写出让机器认知的代码,但是并非各种人都能写出令人认知的代码;
  • Kiss 原则:相通 Python 之禅 里面说的那么,轻松胜于复杂;
  • YAGNI 原则:代码尽量能产生可扩充,但请不要过分重构,因为你无法预感以往;
  • D奔驰G级Y 原则:不要再一次造轮子,除非您不时光还是您造的车轮会比外人的优质;
  • 面向对象编制程序原则:世袭、封装、多态、抽象;

本项目开源了全副工程和代码,可径直编译后开展计划运营。
Wechat第三方平台的安插方法是亟需先登记Wechat开放平台,然后申请第三方应用,经过查证和接口联调确认,就能够使用了。

泛型,从名称想到所包括的意义,正是泛指的类型。好比相恋的人,女生,黄人,黄种人,能够泛称为【人】。

图片 5图片 6

1.4 线程等待

在本章中,线程等待使用的是Join方法,该办法将中止实施当前线程,直到所等待的另二个线程终止。在简约的线程同步中会使用到,但它比较容易,不作过多介绍。

演示代码如下所示:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($"-------开始执行 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}-------");

        // 1.创建一个线程 PrintNumbersWithDelay为该线程所需要执行的方法
        Thread t = new Thread(PrintNumbersWithDelay);
        // 2.启动线程
        t.Start();
        // 3.等待线程结束
        t.Join();

        Console.WriteLine($"-------执行完毕 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}-------");
        // 暂停一下
        Console.ReadKey();
    }

    static void PrintNumbersWithDelay()
    {
        Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 开始打印... 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}");
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 打印:{i} 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}");
        }
    }
}

运作结果如下图所示,伊始试行和推行实现两条音信由主线程打字与印刷;依据其出口的相继可知主线程是等待其它的线程甘休后才输出推行达成那条消息。

图片 7

类设计指南

  • 三个类/接口应该只有一个用项,要符 合单一职务 原则;
  • 只创立重回有用对象的构造函数,当布局函数的参数当先 3 的话,你就应该思谋你的类设计是不是过分肥胖;
  • 接口应该小巧玲珑,其定义要旗帜鲜西汉晰地传达出其负有的行为;
  • 只要生龙活虎种表现存三种落到实处,请酌量动用接口并不是基类;
  • 尽恐怕利用接口将类实行相互影响解耦;
  • 幸免选拔静态类;
  • 毫不使用 new 关键字来禁绝编写翻译器展现相关警示;
public class Book
{
    public virtual void Print()
    {
        Console.WriteLine("Printing Book");
    }
}

public class PocketBook : Book
{
    public new void Print()
    {
        Console.WriteLine("Printing PocketBook");
    }
}

class Program
{
    static void Main(string[] args)
    {
        PocketBook pocketBook = new PocketBook();
        pocketBook.Print();

        ((Book)pocketBook).Print();

        Console.ReadKey();
    }
}

在上述代码段中,大家成立四个基类 book,并定义了三个 Print() 方法,接着我们创立三个子类 PocketBook,并通过 new 关键字来重写基类方法。在项目复杂的情状下,使用这种艺术将促成大家不能够可相信预测是子类调用依然父类调用,使代码复杂度升高。

  • 相应能够将派生类当做基类对象来管理;
  • 不要引用基类的派生类;
  • 制止暴光一个对象依赖的别样对象;
  • 幸免双向重视;
  • 类应该有事态和作为;
  • 类应该保证其里面意况的风度翩翩致性;

本Wechat第三方平台包含了以下职能:

但项目只可以是三个品类。 那么泛型和等级次序之间是什么样关系吗?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils;

namespace TileProcess
{
    public partial class Form1 : Form
    {
        private int _count = 0;
        private int _deltaPixcelX;
        private int _deltaPixcelY;
        private string _inputPath;
        private string _outputPath;
        private int _fromMapZoom;
        private int _toMapZoom;

        private DateTime _startTime;
        private int _lastCount;

        public Form1()
        {
            InitializeComponent();

            _deltaPixcelX = Convert.ToInt32(ConfigurationManager.AppSettings["deltaPixcelX"]);
            _deltaPixcelY = Convert.ToInt32(ConfigurationManager.AppSettings["deltaPixcelY"]);
            _inputPath = ConfigurationManager.AppSettings["inputPath"];
            _outputPath = ConfigurationManager.AppSettings["outputPath"];
            _fromMapZoom = Convert.ToInt32(ConfigurationManager.AppSettings["fromMapZoom"]);
            _toMapZoom = Convert.ToInt32(ConfigurationManager.AppSettings["toMapZoom"]);
        }

        private void btnTileProcess_Click(object sender, EventArgs e)
        {
            this.btnTileProcess.Enabled = false;

            Task.Factory.StartNew(() =>
            {
                LogUtil.Log("开始处理");
                Process();
            });

            Thread thread = new Thread(new ThreadStart(() =>
            {
                int sleepInterval = 1000;
                while (true)
                {
                    Thread.Sleep(sleepInterval);
                    this.BeginInvoke(new Action(() =>
                    {
                        double totalSeconds = DateTime.Now.Subtract(_startTime).TotalSeconds;
                        int avg = (int)(_count / totalSeconds);
                        lblMsg.Text = string.Format("已处理 {0} 张瓦片图", _count);
                        if (_count - _lastCount > 0)
                        {
                            lblSpeed.Text = string.Format("当前速度:{0} 张/每秒,平均速度:{1} 张/每秒", (_count - _lastCount) * 1000.0 / sleepInterval, avg);
                        }
                        _lastCount = _count;
                    }));
                }
            }));
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 瓦片纠偏处理
        /// </summary>
        private void Process()
        {
            _startTime = DateTime.Now;
            Regex regex = new Regex(@"\(d+)\(d+).png", RegexOptions.IgnoreCase);
            for (int i = _fromMapZoom; i <= _toMapZoom; i++)
            {
                int deltaPixcelX = (int)Math.Round(_deltaPixcelX / Math.Round(Math.Pow(2, 18 - i)));
                int deltaPixcelY = (int)Math.Round(_deltaPixcelY / Math.Round(Math.Pow(2, 18 - i)));

                string[] fileArr = Directory.GetFiles(_inputPath + "\" + i, "*.*", SearchOption.AllDirectories);
                foreach (string file in fileArr)
                {
                    ThreadData data = new ThreadData();
                    data.File = file;
                    data.I = i;
                    data.DeltaPixcelX = deltaPixcelX;
                    data.DeltaPixcelY = deltaPixcelY;

                    ThreadUtil.Run((obj) =>
                    {
                        ThreadData d = obj as ThreadData;

                        Match match = regex.Match(d.File);
                        if (match.Success)
                        {
                            int x = Convert.ToInt32(match.Groups[1].Value);
                            int y = Convert.ToInt32(match.Groups[2].Value);

                            string pathTarget = string.Format(string.Format(@"{0}{1}{2}{3}.png", _outputPath, d.I, x, y));
                            if (!File.Exists(pathTarget))
                            {
                                if (!Directory.Exists(Path.GetDirectoryName(pathTarget)))
                                {
                                    Directory.CreateDirectory(Path.GetDirectoryName(pathTarget));
                                }
                                Bitmap bmpNew = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                                Graphics graph = Graphics.FromImage(bmpNew);

                                int deltaX = data.DeltaPixcelX / 256;
                                int deltaY = data.DeltaPixcelY / 256;

                                //临时变量定义
                                string pathSource = null;
                                FileStream fs = null;
                                byte[] bArr = null;
                                MemoryStream ms = null;
                                Bitmap bmpSource = null;

                                //起始
                                pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX, y + deltaY);
                                if (File.Exists(pathSource))
                                {
                                    fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                    bArr = new byte[fs.Length];
                                    int readCount = fs.Read(bArr, 0, bArr.Length);
                                    ms = new MemoryStream(bArr, 0, readCount);
                                    bmpSource = new Bitmap(ms);
                                    graph.DrawImage(bmpSource, 0, 0, new RectangleF(data.DeltaPixcelX % 256, data.DeltaPixcelY % 256, 256 - data.DeltaPixcelX % 256, 256 - data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                    graph.Flush();

                                    fs.Close();
                                    fs = null;
                                    ms.Close();
                                    ms = null;
                                    bmpSource.Dispose();
                                    bmpSource = null;
                                }

                                //右
                                pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX + 1, y + deltaY);
                                if (File.Exists(pathSource))
                                {
                                    fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                    bArr = new byte[fs.Length];
                                    int readCount = fs.Read(bArr, 0, bArr.Length);
                                    ms = new MemoryStream(bArr, 0, readCount);
                                    bmpSource = new Bitmap(ms);
                                    graph.DrawImage(bmpSource, 256 - data.DeltaPixcelX % 256, 0, new RectangleF(0, data.DeltaPixcelY % 256, data.DeltaPixcelX % 256, 256 - data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                    graph.Flush();

                                    fs.Close();
                                    fs = null;
                                    ms.Close();
                                    ms = null;
                                    bmpSource.Dispose();
                                    bmpSource = null;
                                }

                                //下
                                pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX, y + deltaY + 1);
                                if (File.Exists(pathSource))
                                {
                                    fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                    bArr = new byte[fs.Length];
                                    int readCount = fs.Read(bArr, 0, bArr.Length);
                                    ms = new MemoryStream(bArr, 0, readCount);
                                    bmpSource = new Bitmap(ms);
                                    graph.DrawImage(bmpSource, 0, 256 - data.DeltaPixcelY % 256, new RectangleF(data.DeltaPixcelX % 256, 0, 256 - data.DeltaPixcelX % 256, data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                    graph.Flush();

                                    fs.Close();
                                    fs = null;
                                    ms.Close();
                                    ms = null;
                                    bmpSource.Dispose();
                                    bmpSource = null;
                                }

                                //右下
                                pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX + 1, y + deltaY + 1);
                                if (File.Exists(pathSource))
                                {
                                    fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                    bArr = new byte[fs.Length];
                                    int readCount = fs.Read(bArr, 0, bArr.Length);
                                    ms = new MemoryStream(bArr, 0, readCount);
                                    bmpSource = new Bitmap(ms);
                                    graph.DrawImage(bmpSource, 256 - data.DeltaPixcelX % 256, 256 - data.DeltaPixcelY % 256, new RectangleF(0, 0, data.DeltaPixcelX % 256, data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                    graph.Flush();

                                    fs.Close();
                                    fs = null;
                                    ms.Close();
                                    ms = null;
                                    bmpSource.Dispose();
                                    bmpSource = null;
                                }

                                bmpNew.Save(pathTarget);
                                //bmpNew.Save("d:\_临时文件\1234.png"); //测试用

                                bmpNew.Dispose();
                                bmpNew = null;
                                graph.Dispose();
                                graph = null;

                                _count++;
                            } //end if (!File.Exists(pathTarget))
                        } //end if (match.Success)
                    }, data, (ex) =>
                    {
                        this.BeginInvoke(new Action(() =>
                        {
                            lblErrorMsg.Text = "出错:" + ex.Message + "rn" + ex.StackTrace;
                            LogUtil.LogError(ex, "出错");
                        }));
                    }); //end ThreadUtil.Run
                } //end foreach (string file in fileArr)
            } //end for (int i = _fromMapZoom; i <= _toMapZoom; i++)
        }
    }
}

1.5 终止线程

悬停线程使用的章程是Abort方法,当该措施被施行时,将尝试销毁该线程。通过抓住ThreadAbortException充裕使线程被灭亡。但貌似不推荐应用该办法,原因有以下几点。

  1. 使用Abort艺术只是尝试行出卖毁该线程,但不料定能止住线程。
  2. 借使被甘休的线程在施行lock内的代码,那么终止线程会招致线程不安全。
  3. 线程终止时,CLCR-V会保障本人之中的数据布局不会破坏,可是BCL无法担保。

依照以上原因不引进应用Abort办法,在实际项目中貌似接纳CancellationToken来终止线程。

示范代码如下所示:

static void Main(string[] args)
{
    Console.WriteLine($"-------开始执行 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}-------");

    // 1.创建一个线程 PrintNumbersWithDelay为该线程所需要执行的方法
    Thread t = new Thread(PrintNumbersWithDelay);
    // 2.启动线程
    t.Start();
    // 3.主线程休眠6秒
    Thread.Sleep(TimeSpan.FromSeconds(6));
    // 4.终止线程
    t.Abort();

    Console.WriteLine($"-------执行完毕 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}-------");
    // 暂停一下
    Console.ReadKey();
}

static void PrintNumbersWithDelay()
{
    Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 开始打印... 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}");
    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(TimeSpan.FromSeconds(2));
        Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId} 打印:{i} 现在时间{DateTime.Now.ToString("HH:mm:ss.ffff")}");
    }
}

运作结果如下图所示,运维所成立的线程3后,6分钟主线程调用了Abort办法,线程3尚无继续实施便截至了;与预期的结果豆蔻梢头致。

图片 8

属性成员布置指南

  • 同意按私行顺序设置属性;
  • 采用办法并不是性质;
  • 不用使用相互排斥的质量;
  • 性格、方法依然本地点法只应该做意气风发件业务;
  • 绝不通过静态成员公开有事态的目的;
  • 用 IEnumerable 或然 ICollection 来顶替具体的聚合对象作为重回值;
  • 只要属性、参数和再次来到值是字符串可能聚众类型的话,则永恒不应该为空;
  • 尽量地定义具体的参数;
  • 设想采用特定域的值类型并不是基元;

【吸粉】
投票、定时抽取奖金、聚人气抽取奖金、摇风流倜傥摇抽取奖金、观众海报、1元夺宝、发红包、在线捐款 等

事实上超粗略,泛型在概念的时候,是泛指类型;在使用的时候,就要求被钦定,到底使用哪个品种。

View Code

1.6 检测线程状态

线程的状态可透过访问ThreadState质量来检查评定,ThreadState是一个枚举类型,意气风发共有10种情景,状态具体意思如下表所示。

成员名称 说明
Aborted 线程处于 Stopped 状态中。
AbortRequested 已对线程调用了 Thread.Abort 方法,但线程尚未收到试图终止它的挂起的 System.Threading.ThreadAbortException
Background 线程正作为后台线程执行(相对于前台线程而言)。此状态可以通过设置 Thread.IsBackground 属性来控制。
Running 线程已启动,它未被阻塞,并且没有挂起的 ThreadAbortException
Stopped 线程已停止。
StopRequested 正在请求线程停止。这仅用于内部。
Suspended 线程已挂起。
SuspendRequested 正在请求线程挂起。
Unstarted 尚未对线程调用 Thread.Start 方法。
WaitSleepJoin 由于调用 WaitSleepJoin,线程已被阻止。

下表列出引致情况改进的操作。

操作 ThreadState
在公共语言运行库中创建线程。 Unstarted
线程调用 Start Unstarted
线程开始运行。 Running
线程调用 Sleep WaitSleepJoin
线程对其他对象调用 Wait WaitSleepJoin
线程对其他线程调用 Join WaitSleepJoin
另一个线程调用 Interrupt Running
另一个线程调用 Suspend SuspendRequested
线程响应 Suspend 请求。 Suspended
另一个线程调用 Resume Running
另一个线程调用 Abort AbortRequested
线程响应 Abort 请求。 Stopped
线程被终止。 Stopped

演示代码如下所示:

static void Main(string[] args)
{
    Console.WriteLine("开始执行...");

    Thread t = new Thread(PrintNumbersWithStatus);
    Thread t2 = new Thread(DoNothing);

    // 使用ThreadState查看线程状态 此时线程未启动,应为Unstarted
    Console.WriteLine($"Check 1 :{t.ThreadState}");

    t2.Start();
    t.Start();

    // 线程启动, 状态应为 Running
    Console.WriteLine($"Check 2 :{t.ThreadState}");

    // 由于PrintNumberWithStatus方法开始执行,状态为Running
    // 但是经接着会执行Thread.Sleep方法 状态会转为 WaitSleepJoin
    for (int i = 1; i < 30; i++)
    {
        Console.WriteLine($"Check 3 : {t.ThreadState}");
    }

    // 延时一段时间,方便查看状态
    Thread.Sleep(TimeSpan.FromSeconds(6));

    // 终止线程
    t.Abort();

    Console.WriteLine("t线程被终止");

    // 由于该线程是被Abort方法终止 所以状态为 Aborted或AbortRequested
    Console.WriteLine($"Check 4 : {t.ThreadState}");
    // 该线程正常执行结束 所以状态为Stopped
    Console.WriteLine($"Check 5 : {t2.ThreadState}");

    Console.ReadKey();
}

static void DoNothing()
{
    Thread.Sleep(TimeSpan.FromSeconds(2));
}

static void PrintNumbersWithStatus()
{
    Console.WriteLine("t线程开始执行...");

    // 在线程内部,可通过Thread.CurrentThread拿到当前线程Thread对象
    Console.WriteLine($"Check 6 : {Thread.CurrentThread.ThreadState}");
    for (int i = 1; i < 10; i++)
    {
        Thread.Sleep(TimeSpan.FromSeconds(2));
        Console.WriteLine($"t线程输出 :{i}");
    }
}

运转结果如下图所示,与预期的结果相像。

图片 9

此外设计指南

  • 抛出非凡并不是回去某类别型的景色值;
  • 提供整机而有意义的格外新闻;
  • 抛出确切的最实际的万分;
  • 无须通过 try - catch 形式蒙蔽十分;
  • 正确管理异步代码中的卓殊;
  • 调用事件委托前先推断是或不是为空;
event EventHandler<string> Notify;
protected virtual void OnNotify(string args)
{
    Notify?.Invoke(this, args);
}
  • 利用受有限帮忙的虚方法来触发每种事件;
  • 考虑增多属性别变化化事件;
  • 当接触事件时要保管 sender != nulll;
  • 豆蔻梢头经适度的话,请思忖接收泛型节制;
class SomeClass
{
}

/// <summary>
/// 不推荐
/// </summary>
class MyClass1
{
    void SomeMethod<T>(T t)
    {
        object temp = t;
        SomeClass obj = (SomeClass)temp;
    }
}

/// <summary>
/// 推荐
/// </summary>
class MyClass2
{
    void SomeMethod<T>(T t) where T :SomeClass
    {
        SomeClass obj = t;
    }
}
  • 在回来 LINQ 表明式以前总括它的结果;
  • 设若不是必需,不要使用 thisbase 关键字;

【持续显现】
微官方网址、微会员、积分商号、卡券、Wechat支付、分类音信、电影排片 等

即,使用时,就不在是泛指类型,而是一定类型。

拍卖效能:小编要好计算机每秒管理大致350张瓦片图,1到18级瓦片共100多万张图片,大约须求处理50分钟。

1.7 线程优先级

Windows操作系统为抢占式三十二线程(Preemptive multithreaded卡塔尔国操作系统,是因为线程可在别的时刻甘休(被枪占)并调治另二个线程。

Windows操作系统中线程有0(最低) ~ 31(最高)的优先级,而优先级越高所能占用的CPU时间就越来越多,分明有个别线程所处的预先级须求思忖过程优先级绝对线程优先级五个先行级。

  1. 进度优先级:Windows辅助6个经过优先级,分别是Idle、Below Normal、Normal、Above normal、High 和Realtime。默认为Normal
  2. 周旋线程优先级:相对线程优先级是相持于经过优先级的,因为经过包括了线程。Windows匡助7个绝对线程优先级,分别是Idle、Lowest、Below Normal、Normal、Above Normal、Highest 和 Time-Critical.默认为Normal

下表计算了经过的开始时期级线程的周旋优先级优先级(0~31)的照耀关系。粗体为相对线程优先级,斜体为经过优先级

Idle Below Normal Normal Above Normal High Realtime
Time-Critical 15 15 15 15 15 31
Highest 6 8 10 12 15 26
Above Normal 5 7 9 11 14 25
Normal 4 6 8 10 13 24
Below Normal 3 5 7 9 12 23
Lowest 2 4 6 8 11 22
Idle 1 1 1 1 1 16

而在C#次第中,可改正线程的相持优先级,须要安装ThreadPriority天性,可安装为ThreadPriority枚举类型的三个值之后生可畏:Lowest、BelowNormal、Normal、AboveNormal 或 Highest。CL奇骏为投机保留了IdleTime-Critical优先级,程序中不得设置。

示范代码如下所示。

static void Main(string[] args)
{
    Console.WriteLine($"当前线程优先级: {Thread.CurrentThread.Priority} rn");

    // 第一次测试,在所有核心上运行
    Console.WriteLine("运行在所有空闲的核心上");
    RunThreads();
    Thread.Sleep(TimeSpan.FromSeconds(2));

    // 第二次测试,在单个核心上运行
    Console.WriteLine("rn运行在单个核心上");
    // 设置在单个核心上运行
    System.Diagnostics.Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
    RunThreads();

    Console.ReadLine();
}

static void RunThreads()
{
    var sample = new ThreadSample();

    var threadOne = new Thread(sample.CountNumbers);
    threadOne.Name = "线程一";
    var threadTwo = new Thread(sample.CountNumbers);
    threadTwo.Name = "线程二";

    // 设置优先级和启动线程
    threadOne.Priority = ThreadPriority.Highest;
    threadTwo.Priority = ThreadPriority.Lowest;
    threadOne.Start();
    threadTwo.Start();

    // 延时2秒 查看结果
    Thread.Sleep(TimeSpan.FromSeconds(2));
    sample.Stop();
}

class ThreadSample
{
    private bool _isStopped = false;

    public void Stop()
    {
        _isStopped = true;
    }

    public void CountNumbers()
    {
        long counter = 0;

        while (!_isStopped)
        {
            counter++;
        }

        Console.WriteLine($"{Thread.CurrentThread.Name} 优先级为 {Thread.CurrentThread.Priority,11} 计数为 = {counter,13:N0}");
    }
}

运作结果如下图所示。Highest占用的CPU时间分明多于Lowest。当程序运营在具备骨干上时,线程可以在分裂大旨同时运维,所以HighestLowest差别会小部分。

图片 10

可维护性指南

  • 办法内部的代码段尽量不要超过 7 行;
  • 保证全部成员个人,类的类型默以为为 internal sealed
  • 防止重新规范;
  • 在其蕴藉的命名空间内命名程序集;
  • 将源文件命名叫它所包含的门类;
  • 将源文件的剧情限定为风姿浪漫系列型;
  • 将区别的逻辑函数放到同一个局地类中;
  • 在运用三个门类时,使用 using 关键字导入须要的命名空间,实际不是体系的完全空间标记;
  • 无须接收法力数;
  • 只有当类型简单的说时才使用 var 关键字;
  • 概念变量时尽量地初阶化;
  • 在互相独立的代码段中定义临时变量;
  • 若对象有集聚需求早先化的话在张开对象开始化的还要扩充联谊开头化;
  • 永不显式进行 bool 值的可比;
  • 幸免嵌套循环;
  • 在使用 ifelsedowhileforforeachcase 的还要选择 {}
  • switch case 代码段中增添 default 逻辑;
  • 在颇负的 ifelse if 后再加多 else;
  • 幸免使用三个重临值;
  • 其三方Wechat平台,八线程编制程序种类。思量采取简便的标准语句替代 if else
  • 封装属性、方法或一些函数中的复杂表明式;
  • 再贴切的处境下品尝重载方法;
  • 应用可选参数来代表重载;
  • 防止采取命名参数;
  • 幸免定义超过3个参数的签字;
  • 防止函数具名称叫布尔类型;
  • 决不将参数作为有时变量使用;
  • 将格局作为操作;
  • 不要疏解代码;

【管理考核】
Computer手提式有线电话机双后台、经营发卖二维码、后台顾客管理、操作日志 等备注:

好比,定义时,定义了一人。但在利用时,必需领悟钦点,到底是黄种人如故黄人。

瓦片图纠正偏差或偏向前后相比较:

1.8 前台线程和后台线程

在CLWrangler中,线程要么是前台线程,要么正是后台线程。当三个进度的保有前台线程甘休运作时,CL纳瓦拉将强制截止仍在运作的任何后台线程,不会抛出特别。

在C#中可透过Thread类中的IsBackground属性来钦赐是不是为后台线程。在线程生命周期中,任哪一天候都可以前台线程变为后台线程。线程池中的线程默以为后台线程

亲自过问代码如下所示。

static void Main(string[] args)
{
    var sampleForeground = new ThreadSample(10);
    var sampleBackground = new ThreadSample(20);
    var threadPoolBackground = new ThreadSample(20);

    // 默认创建为前台线程
    var threadOne = new Thread(sampleForeground.CountNumbers);
    threadOne.Name = "前台线程";

    var threadTwo = new Thread(sampleBackground.CountNumbers);
    threadTwo.Name = "后台线程";
    // 设置IsBackground属性为 true 表示后台线程
    threadTwo.IsBackground = true;

    // 线程池内的线程默认为 后台线程
    ThreadPool.QueueUserWorkItem((obj) => {
        Thread.CurrentThread.Name = "线程池线程";
        threadPoolBackground.CountNumbers();
    });

    // 启动线程 
    threadOne.Start();
    threadTwo.Start();
}

class ThreadSample
{
    private readonly int _iterations;

    public ThreadSample(int iterations)
    {
        _iterations = iterations;
    }
    public void CountNumbers()
    {
        for (int i = 0; i < _iterations; i++)
        {
            Thread.Sleep(TimeSpan.FromSeconds(0.5));
            Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
        }
    }
}

运维结果如下图所示。当前台线程12次巡回甘休之后,创制的后台线程和线程池线程都会被CL福睿斯强制截至。

图片 11

命名指南

  • 不要在变量、参数和花色成员中隐含数字;
  • 并不是在字段加多前缀;
  • 毫无选取缩写;
  • 成员、参数和变量定义要基于它们代表的含义;
  • 选取名词、名词短语或许形容词来定义类型;
  • 利用描述性名称命名泛型参数;
  • 在类成员中不要再度定义和类相似的名号;
  • 成员定义可参照他事他说加以考查 .Net Framework 的概念格局;
  • 制止选拔可能被误会的段名称或字段;
  • 正确定义属性;
  • 在命名方式或局地函数时选择谓词或谓词对象;
  • 运用名称、层、谓词和作用注明命名空间;
  • 采纳动词或动词前缀来定义事件;
  • 使用 ingend 后缀来表明事件预管理和发送事件;
  • 使用 on 前缀来定义事件管理程序;
  • 使用 Async 或者 TaskAsync 来标识异步方法;

风姿浪漫、功效设计

泛型的接收

图片 12

1.9 向线程传递参数

向线程中传递参数常用的有两种办法,布局函数传值、Start方法传值和Lambda说明式传值,通经常用Start方法来传值。

示范代码如下所示,通过两种艺术来传递参数,告诉线程中的循环最后必要循环几遍。

static void Main(string[] args)
{
    // 第一种方法 通过构造函数传值
    var sample = new ThreadSample(10);

    var threadOne = new Thread(sample.CountNumbers);
    threadOne.Name = "ThreadOne";
    threadOne.Start();
    threadOne.Join();

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

    // 第二种方法 使用Start方法传值 
    // Count方法 接收一个Object类型参数
    var threadTwo = new Thread(Count);
    threadTwo.Name = "ThreadTwo";
    // Start方法中传入的值 会传递到 Count方法 Object参数上
    threadTwo.Start(8);
    threadTwo.Join();

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

    // 第三种方法 Lambda表达式传值
    // 实际上是构建了一个匿名函数 通过函数闭包来传值
    var threadThree = new Thread(() => CountNumbers(12));
    threadThree.Name = "ThreadThree";
    threadThree.Start();
    threadThree.Join();
    Console.WriteLine("--------------------------");

    // Lambda表达式传值 会共享变量值
    int i = 10;
    var threadFour = new Thread(() => PrintNumber(i));
    i = 20;
    var threadFive = new Thread(() => PrintNumber(i));
    threadFour.Start();
    threadFive.Start();
}

static void Count(object iterations)
{
    CountNumbers((int)iterations);
}

static void CountNumbers(int iterations)
{
    for (int i = 1; i <= iterations; i++)
    {
        Thread.Sleep(TimeSpan.FromSeconds(0.5));
        Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
    }
}

static void PrintNumber(int number)
{
    Console.WriteLine(number);
}

class ThreadSample
{
    private readonly int _iterations;

    public ThreadSample(int iterations)
    {
        _iterations = iterations;
    }
    public void CountNumbers()
    {
        for (int i = 1; i <= _iterations; i++)
        {
            Thread.Sleep(TimeSpan.FromSeconds(0.5));
            Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
        }
    }
}

运维结果如下图所示,与预期结果相符。

图片 13

性能指南

  • 使用 Any() 判断 IEnumerable 是不是为空 ;
  • 仅对低密集型活动使用异步;
  • 对于 CPU密集型使用 Task.Run
  • 幸免同期将 async/awaitTask.Wait 混合使用;
  • 避免 async/await 在单线程意况下现身死锁;

1)设计目的

◇ 为Wechat服务号提供运行及管理所需的各类效能,富含微官方网站、微会员、活动基本、经营出售协理、Wechat支付。

◇ 提供轻松友好的成效画面,使非专门的学业本领职员也能够轻巧的行使。

◇ 提供可独立于系统之外的插件功效或接口,可任性对接此外系统或效能模块。

 

本文由必赢网上注册发布于必赢网上注册,转载请注明出处:其三方Wechat平台,八线程编制程序种类

关键词:

拿到Computer的互连网连接状态,去掉html标签方法

public static string CleanHtml(string strHtml) { strHtml = Regex.Replace(strHtml, @"(script(.+?)/script)|(style(.+?)/style)", "", RegexOptions.IgnoreCa...

详细>>

net中汉字转变到为拼音,并发编制程序杰出实例

1.运用途景 将汉字调换为拼音(eg:"作者爱你"———"WOAINI"卡塔尔(قطر‎ 取各样汉字的首字母(eg:"作者是华夏人...

详细>>

使用线程池,记录日志

        由于UDP探讨并没有必要进行规定的连续几日,程序中能够无需思谋连接和有些十分的捕获职业。在多少对数...

详细>>

并实行多少级联转载,自定义日期的时分秒

1、在Python中要想定义的艺术只怕变量只在类内部采纳不被外表调用,能够在措施和变量前面加  两个  下划线 C# 结...

详细>>