Web Analytics
yangyang

码农兼一个普普通通小青年

All Posts


告别暴力终止线程

有时候需要让一个线程终止运行,.NET Framework的Thread类中提供了Abort方法,调用某个线程实例对象的Abort方法,可以让该线程类抛出一个ThreadAbortException从而终止该线程的运行。但使用Abort方法终止一个线程对象显得比较暴力,而且可能会有很多潜在的问题,尤其是一个线程调用另外一个线程的Thread.Abort方法终止时。好消息是从.NET 5.0开始Thread.Abort方法就已经被弃用,如果调用就会抛出“PlatformNotSupportedException”,本文主要介绍简单粗暴杀手线程的可能危害,以及如何优雅地退出线程的方法。 …

Thread.Abort cooperative cancellation model CancellationTokenSource

Aho-Corasick多模式匹配算法

aho-corasick-automation简称AC自动机算法,它是一个经典的多模式匹配算法,它借鉴了KMP算法的思想,可以由有限状态机来表示。具体实现中可以通过构建状态转移函数,失配函数,结果输出函数来实现。用于匹配的FSA跟输入的字符串无关,只跟模式串有关。匹配中如果发生失败,则FSA回退到某一状态,而输入的字符串则无须回退,从而能够实现通过一次遍历给定的字符串来查找所有的关键字匹配。 …

aho-corasick pattern-match automation kmp

使用Mono.Cecil将函数注入到模块的初始化构造器中

本文介绍了模块默认的模块初始化构造(Module Initializer)及其作用,进一步介绍了如何使用Mono.Cecil这一强大的IL语言修改器来修改已经编译好的程序集,来将注册AppDomain的AssemblyResolve事件逻辑,注入到模块的初始化构造器中,以实现将第三方依赖dll嵌入到资源文件中,程序集在动态加载时能够自动加载依赖的dll的功能。 …

Mono.Cecil Injection MSIL AppDomain Assembly Resolve Module Initializer Fody

将.NET应用程序发布为单一的可执行文件

本文简单介绍了在.NET中将程序打包为单文件的原理,并在.NET Framework和.NET Core中分别做了演示。在.NET Core中单文件部署比较简单,Visual Studio中自带的发布选项就能实现单文件部署。而.NET Framework中则需要手动添加依赖的dll到资源文件并将其“生成操作”设置为“嵌入的资源”,并且还需要注册AppDomain的AssemblyResolve事件,编写代码手动到资源文件里面加载对应的dll,比较繁琐。但借助第三方的工具比如Costura这个类库,就能十分方便的不用做任何修改的情况下,就能将程序发布为单文件应用。 …

Costura Single exe

使用命名管道进行进程间通讯

在某些情况下,我们需要在本机上的多个进程间进行通讯(inter process communication,IPC)。进程间进行通讯的方式有很多种,比如共享内存、TCP/IP、命名管道(Named Pipes)、Windows消息等等。本文主要介绍命名管道这种进程间通讯的使用方法。 …

NamedPipe IPC

从Dictionary中key为大小写不敏感的字符串类型说起

本文由一个在Dictionary中使用String作为key,且支持大小写不敏感匹配的例子来说明Dictionary的内部原理。由Key获取hash值是Dictionary实现的关键。在Dictionary声明的时候,可以通过构造函数传递IEqualityComparer参数来指定比较器,通过该对象来获取哈希值。如果不提供这个参数,则会在内部判断Key是否实现了IEquatable泛型接口,如果提供了,则使用该泛型接口中定义的GetHashCode来获取哈希值,否则会根据Key的类型生成一个通用的EqualityComparer,这个通过的EqualityComparer的参数是object类型,所以如果Key的类型为结构体,则必须为其实现IEquatable泛型接口,否则就会产生装箱从而严重影响性能。 …

Dictionary Hash StringComparer IEquatable IEqualityComparer

解决WinForm中Chart控件偶发的一言不合就报错画红叉的问题

在WinForm中,使用自带的System.Windows.Forms.DataVisualization.Charting图表控件绘图时,在极其偶然的情况下,由于一些数据或者参数不对,会导致图表绘图区出现一个大大的红色叉叉,同时会弹出报错窗体。这个问题在我司的一个程序中非常罕见,且不容易重现,最近在处理这个问题时,通过控制变量,使得这一问题比较容易重现,从而为找到问题打开了突破口,这里记录一下。 …

CandleStick MSChart Red-Cross StackOverflow

C++内存管理基础

本文也是候捷《C++内存管理机制》的笔记,介绍了C++原始内存分配的基本方法,优缺点,以及介绍了一个简单的内存池,虽然在Modern C++中已经不建议直接管理内存分配后的指针,而是采用智能指针的方式。但是这些只是对原始内存分配的一些包装或处理,所以这里记录一下。 基本方式 《Effective C++》这本书开篇就指出,C++由几大部分组成: C语言部分。C++是以C为基础,C++经过编译器处理后就是C语言。在C++中仍然保留了很多C语言的用法,比如区块(blocks)、语句(statement),数组(arrays)、指针(pointer)等等。所以C语言中的一些内存分配方法,在C++中仍然能够使用。 面向对象,就是C with Class,包括类、封装、继承、多态等等。 模版,Template C++是C++泛型编程的一部分。这一点跟C#中的泛型编程个人感觉区别巨大。但C++中的模版 …

memory management memory pool allocator embedded pointer

C++中的模版模版参数和模版别名的使用

最近在看候捷的C++系列视频教程,其中有一个例子讲到了使用迭代器特性(iterator_traits)和使用模版模版参数(template template parameter)以及模版别名(alias template)来完成同一件事情,非常的经典,我这里记录一下。 事情的起因 事情的缘由是要比较在不同类型的容器类型(vector、deque、set等等)中,对象是否有moveable的相关构造函数 对容器的各种操作性能的影响。所以要编写一个通用的模版方法,允许接受不同的模版参数,以及不同的数据类型,并能输出调用各种操作(拷贝构造,移动构造,赋值构造)耗费的时间等的时间。 为了方便进行,这里编写了两个简化版本的String类,一个名为MyString的类带有各种移动构造,拷贝,赋值函数(Big Five) #include #include # …

template template parameter alias template iterator traits

“异常”应该仅用于真正的异常情况而不应将其当作正常处理流程来使用

在《Writing High-Performance .NET Code》这本书中,作者指出,抛出“异常”(Exception)的开销十分高昂,很大一部分原因是.NET的异常对象中包含了丰富的信息,“异常”必须是为真正的异常情况服务,在这种情况下性能可以退居其次。 作者还举了例子,说明了三个事实: 抛出“异常”的方法比空方法慢了数千倍。 “异常”抛出的层数越深,速度就越慢。 和只用1个catch相比,多个catch语句的影响比较轻微,但仍然影响很明显。 使用catch捕获异常的开销可能不大,但是要访问Exception对象的StackTrace属性开销可能会非常高。因为需要由“异常”指针重建调用栈,并转译成可读文本。作者反复强调,“异常”应该仅用于真正的异常情况,如果将“异常”作为正常的处理流程来使用,会让程序毫无性能可言。 …

Exceptions