HueiFeng冯辉,HueiFeng,.NET,.NET Core,Docker,k8s(c) {year} Moonglade2024-03-19T06:17:26ZMoonglade v11.2-previewCF239415-18C6-4F58-8316-2568E1207954理解并掌握C#的Channel:从使用案例到源码解读(一)2023-09-24T15:33:35Z2023-09-24T15:33:35ZHueiFeng695979933@qq.com引言
在C#的并发编程中,Channel是一种非常强大的数据结构,用于在生产者和消费者之间进行通信。本文将首先通过一个实际的使用案例,介绍如何在C#中使用Channel,然后深入到Channel的源码中,解析其内部的实现机制。
使用案例一:文件遍历和过滤
在我们的使用案例中,我们需要遍历一个文件夹及其所有子文件夹,并过滤出具有特定扩展名的文件。在此,我们使用了C#的Channel来实现这个任务。
首先,我们创建了一个名为EnumerateFilesRecursively的方法,这个方法接受一个文件夹路径作为参数,并返回一个ChannelReader<string>。这个方法中,我们创建了一个有界的Channel,然后在一个单独的任务中遍历指定的文件夹及其所有子文件夹,并将找到的每个文件的路径写入Channel。当遍历完成后,我们关闭Channel的写入端。 …874735CB-D6B6-4C40-9A8C-0CD9F15E1D5E.NET对象的内存布局2023-08-06T14:14:48Z2023-08-06T14:14:48ZHueiFeng695979933@qq.com在.NET中,理解对象的内存布局是非常重要的,这将帮助我们更好地理解.NET的运行机制和优化代码,本文将介绍.NET中的对象内存布局。
.NET中的数据类型主要分为两类,值类型和引用类型。值类型包括了基本类型(如int、bool、double、char等)、枚举类型(enum)、结构体类型(struct),它们直接存储值。引用类型则包括了类(class)、接口(interface)、委托(delegate)、数组(array)等,它们存储的是值的引用(数据在内存中的地址)。
值类型的内存布局
值类型的内存布局是顺序的,并且是紧凑的。例如,定义的结构体SampleStruct,其中包含了四个int类型字段,每个字段占用4个字节,因此整个SampleStruct结构体在内存中占用16个字节。
public struct SampleStruct
{
public int Value1; …4CDA38FE-CBD2-4906-B095-E9B6ED245E48C#抽象静态方法2023-07-15T14:18:18Z2023-07-15T14:18:18ZHueiFeng695979933@qq.com 抽象静态方法
在C# 11中,引入了对抽象静态接口成员的支持。这个特性可以让你在接口中定义静态抽象方法、属性、或事件。具体来说,一个接口可以定义一个或多个抽象静态成员,这些成员没有具体的实现。任何实现该接口的类或结构必须提供这些成员的静态实现。这就像实现普通接口成员一样,只不过是静态的。当然,你也可以基于它来实现一些设计模式,本文将展开介绍。
单例模式:静态抽象成员可以用于实现单例模式。在这种模式中,一个类只能有一个实例,并提供一个全局访问点。
public interface ISingleton
{
static abstract ISingleton Instance { get; }
}
public class Singleton : ISingleton
{
private static readonly Singleton _instance = new …1E4C7792-92DC-449C-BD24-0F0A8A79C9D4.NET Native AOT的静态库与动态库2023-05-16T14:18:48Z2023-05-16T14:18:48ZHueiFeng695979933@qq.com.NET不仅可以使用 C静态库与动态库,也可以将.NET实现的函数导出为C静态库与动态库。在没有Native Aot之前,.NET只能通过P/Invoke享受C/C++生态,而在Native Aot之后,不仅可以享受这些生态,还可以开发SDK供其他语言调用。
.NET Native AOT的NativeLib参数用于指定本机库的类型。在.NET 7中,该参数有两个选项:Static和Shared。
Static: 生成静态库,意味着所有依赖项都将被编译到生成的可执行文件中,因此它更适合独立应用程序或需要最小化依赖项的应用程序。
Shared: 生成动态库,意味着依赖项将被编译为单独的本机库,并在运行时动态加载。这种方法可以减少生成文件大小,并且更适合需要共享依赖项的应用程序,所以它也被称为共享库。
使用UnmanagedCallersOnly特性可以将C#函数导出提供给C调用, …91EA438E-0A40-4C89-B670-D1ADBC798DFC使用dotnet-monitor分析在Kubernetes的应用程序:Sidecar模式2022-08-17T15:32:36Z2022-08-17T15:32:36ZHueiFeng695979933@qq.comdotnet-monitor可以在Kubernetes中作为Sidecar运行,Sidecar是一个容器,它与应用程序在同一个Pod中运行,利用Sidecar模式使我们可以诊断及监控应用程序。
如下图所示,这是我们最终要实现的目标,通过可视化界面查看应用程序的指标信息。
file
应用服务
创建dotnetmonitor.yaml文件,如下所示。
apiVersion: apps/v1
kind: Deployment
metadata:
name: dotnet-monitor-example
spec:
replicas: 3
selector:
matchLabels:
app: dotnet-monitor-example
template:
metadata:
annotations:
prometheus. …83A2614E-9688-41C8-8C41-C587502BAA4Awsl2 内存限制2022-07-27T15:21:00Z2022-07-27T15:21:00ZHueiFeng695979933@qq.com在C:\Users\<UserName>\.wslconfig创建一个文件,配置如下所示。
[wsl2]
memory=4GB
swap=8GB
swap类似于Windows的虚拟内存,从硬盘中划分出一个分区,在物理内存不够时,就会将硬盘空间虚拟成内存使用,用于解决内存不足的情况。
配置格式:
[wsl2]
memory=size
processors=number
swap=size
localhostForwarding=bool
在配置设置完之后,执行wsl --shutdown命令进行关闭,随后执行wsl命令再次启动即可。
memory:限制内存
swap:交换分区
processors:限制核心数
localhostForwarding:关闭默认连接,将WSL2本地主机绑定到Windows本地主机
91BCF231-42C7-4C0B-A149-9A957A539874利用Windbg分析Magicodes.IE一次错误编写导致内存问题2021-12-11T06:54:45Z2021-12-11T06:54:45ZHueiFeng695979933@qq.com由于这近一年时间一直忙于写书和工作,一直没有水文,但是近期有几位朋友使用我们的Magicodes.IE反馈在导出过程中内存暴涨...好吧,不管怎样,不能苦了我们朋友,接下来我们通过windbg来看一下什么原因导致的。
接下来我们先通过address -summary来看一下当前应用内存占用量。
0:000 !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 581 7df8`ef0c9000 ( 125.972 TB) 98.42%
unknown 1678 …6B08EC4E-24A5-4BB3-ADF7-F8D07619F5C1【Azure DevOps系列】Azure DevOps构建.NET EFCore应用程序2021-05-30T04:46:38Z2021-05-30T04:46:38ZHueiFeng695979933@qq.com本章我们将看到如何通过Azure DevOps使用EFCore CLI工具将我们的EFCore应用程序进行数据库重建,当然这种操作我不建议使用,建议使用CLI生成sql脚本形式进行发布并迁移。
设置代理服务器sdk
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '3.x'
安装dotnet-ef
安装Entity Framework Core CLI工具,用于后面对数据库的操作
- task: CmdLine@2
displayName: 'install dotnet-ef'
inputs:
script: 'dotnet tool install -g dotnet-ef'
删除数据库
dotnet ef database drop --project <path to your …41F9E03F-7E43-4184-BA3C-B771401053C4.NET RulesEngine(规则引擎)2021-04-29T15:13:59Z2021-04-29T15:13:59ZHueiFeng695979933@qq.com一次偶然的机会,让我拿出RulesEngine去完成一个业务,对于业务来说主要是完成一个可伸缩性(不确定的类型,以及不确定的条件,条件的变动可能是持续增加修改的)的业务判断。比如说完成一个成就系统,管理员可创建,对于成就来说有一次性解锁、日常、周常式,还有随时重置,每次达成都触发的,面对着成就任务的增加,那对于程序员来说,如果每次都去增加修改这些成就任务简直是太头疼了。好了,对此大家应该有一个简单的了解了,那跟着笔者往下走,我们看看如何在.NET中使用非常少的代码去完成一个简单的动态逻辑处理。
RulesEngine 概述
RulesEngine是Microsoft推出的一个规则引擎项目,用于系统中抽象出的业务逻辑/规则/策略。在我们开发的过程中,避免不了的是跟这种反反复复的业务逻辑进行处理,而对于这种动态的规则来说的话,它是比较优雅的一种方式,使用我们减少了对我们代码或者说项目的修改。 …A4118DBF-0C7B-4658-9017-F8498E038D60在ASP.NET Core中使用ViewComponent2021-04-10T03:40:30Z2021-04-10T03:40:30ZHueiFeng695979933@qq.com前言
在之前的开发过程中,我们对于应用或者说使用一些小的组件,通常使用分布页(partial view),再往前在Web Form中我们会进行应用WEB Control,好吧提及一个关键性代码TagPrefix:TagName,通过这种的标记我们便可以在我们web form中进行引入我们的组件,当然自从.NET MVC之后呢,就已经没有了WebControl,而对于.NET Core后,又多了一个特性ViewComponent。
对于ViewComponent看起来它类似于小的控制器,而对于我们小的组件或者小部分通用型功能,可通过ViewComponent进行实现,比如说留言栏、菜单等等。
ViewComponent是由两部分组成,一部分是类(通常该类集成与ViewComponent),而另外一部分是视图(Razor和普通的View一样),当然ViewComponent同样也支持POCO, …88056697-3937-49EA-9257-07B3FEA3F28F.NET初探源代码生成(Source Generators)2021-03-16T12:43:48Z2021-03-16T12:43:48ZHueiFeng695979933@qq.com前言
Source Generators顾名思义代码生成器,可进行创建编译时代码,也就是所谓的编译时元编程,这可让一些运行时映射的代码改为编译时,同样也加快了速度,我们可避免那种昂贵的开销,这是有价值的。
实现ISourceGenerator
集成ISourceGenerator接口,实现接口用于代码生成策略,它的生命周期由编译器控制,它可以在编译时创建时创建并且添加到编译中的代码,它为我们提供了编译时元编程,从而使我们对C#代码或者非C#源文件进行内部的检查。
[Generator]
class CustomGenerator: ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
throw …7946ECA2-A86C-4CE0-AB9E-0FCC73CBDFA6.NET探索模型路由约定实现伪静态2021-02-19T10:49:28Z2021-02-19T10:49:28ZHueiFeng695979933@qq.com概述
IPageRouteModelConvention接口用于自定义PageRouteModel,这个对象在Microsoft.AspNetCore.Mvc.ApplicationModels命名空间中,
代表着Razor Page路由设置,换句话说我们可以通过实现该接口覆盖默认的实现。
该接口需要实现一个成员void Apply(PageRouteModel model)。通过这个方法,我们可以访问有关当前路由设置的元数据,并根据需要对其内容进行修改。
下面示例,将解决提供一个伪静态的解决方案,因此我们可以通过index.html about.html....去访问我们的页面,也就是说我们可以从Index-Index.html的支持
public class HtmlExtensionPageRouteModelConvention : …67B3E5EA-90EC-45AD-9266-9A3D0AA8A13E.NET中使用DebuggerDisplay轻松定制调试2021-02-12T12:46:59Z2021-02-12T12:46:59ZHueiFeng695979933@qq.com前言
对于调试的方式有多种,不过在今天我们将看到的监视窗口对变量的监视,当然在这里我们是定制内部的变量值,或者说变量的显示与计算的内容。
注:监视窗口在调试时可以一次显示多个变量。“快速监视”对话框一次显示一个变量。
file
DebuggerDisplayAttribute
在下面示例中,我们在类上添加DebuggerDisplay,添加字符串:("Name={Name},Age={Age}"):
class Program
{
static void Main(string[] args)
{
Student student = new Student()
{
Name = Mr.A,
Age = 18
}; …F7306072-050F-488B-B2B2-39CCF78275FA.NET探索平台条件编译2021-01-17T14:36:04Z2021-01-17T14:36:04ZHueiFeng695979933@qq.com前言
今天偶然机会,翻了一下大学期间的书籍《C程序设计》,好吧,当我翻着翻着,翻到了符号常量(#define指令)中,是啊,这是一个预处理器指令,记得在Magicodes.IE中针对平台选择不同的库,哈哈,这是一个典型的根据平台进行条件处理,好吧,
根据这些内容,让我感觉在今天,我需要对#define指令以及在.NET中的平台条件处理,以及平台的条件编译进行记录一下。
file
define
我们可通过define来定义符号,然后将符号用在#if指令表达式中,如下所示:
#define PI
通过上面这些内容可能很难去了解这该如何使用,其实#define在我们的编码过程中也是很少去使用的,我们继续往下看。
其实对于预处理器,在我们调试以及运行时的作用是比较大的,比如说对某些代码限制编译,另一方变其实还可以对代码进行环境或者版本的控制,这些都是Ok的,最后我们结合着控制语句#if来看一下: …BF6EB13E-F56A-4F9B-AB2E-5F930856FA9E【Azure DevOps系列】Azure DevOps EFCore命令式脚本部署到SQL数据库2020-12-09T13:23:52Z2020-12-09T13:23:52ZHueiFeng695979933@qq.com构建迁移脚本
为了构建迁移脚本,我们将需要使用EF Tools for Command Line Interface。这些工具在Microsoft.EntityFrameworkCore.Tools提供。
迁移脚本
现在我们将通过 dotnet ef migrations script –p path to your csproj with migrations -o $(Build.ArtifactStagingDirectory)\migrations\scripts.sql –i来迁移我们的脚本,在如下代码片段中我将脚本进行迁移出来并且输出到指定的路径 -o $(Build.ArtifactStagingDirectory)/migrations/scripts.sql中, -i代表生成可用于任何迁移的数据库的脚本。
- task: CmdLine@2 …2E963547-9B39-46BD-B93A-8AEC8FFA127D探索.NET平台中的SIMD内在函数Vector2020-12-01T02:57:11Z2020-12-01T02:57:11ZHueiFeng695979933@qq.com概述
Vector(向量)是一种序列式容器,事实上和数组差不多,但它比数组更优越。一般来说数组不能动态拓展,因此在程序运行的时候不是浪费内存,就是造成越界。而Vector刚好弥补了这个缺陷,它的特征是相当于可分配拓展的数组(动态数组),它的随机访问快,在中间插入和删除慢,但在末端插入和删除快。
什么是SIMD?
SIMD是Single Instruction Multiple Data的缩写,通常中文译为单指令多数据流,通俗来讲的话是:对多个数据执行同一个CPU指令,以达到平行运算的目的.
在GPU之前我们会通过CPU来运行该项技术来增加图片的运算速度,例如Intel的MMX、SSE、SSE2、AVX,AMD的3DNow!等等,都是来使用SIMD
为基础的概念,在GPU技术突飞猛进的今天,CPU的SIMD技术很少用在了图片运算方面了,更多的是在资料库或者其他用途上。
SIMD
它适用于机器 …82DC7BE7-292B-48F4-9192-82128D27D220Vs编译时RazorTagHelper - DOTNET_HOST_PATH is not set2020-11-17T12:26:11Z2020-11-17T12:26:11ZHueiFeng695979933@qq.com今天听朋友说遇到一个问题,打开一个aspnetcore2.2的项目工程,发现挺有意思,缺少环境变量DOTNET_HOST_PATH
file
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 MSB4018 “RazorTagHelper”任务意外失败。
System.InvalidOperationException: DOTNET_HOST_PATH is not set
在 Microsoft.AspNetCore.Razor.Tasks.DotNetToolTask.get_DotNetPath()
在 Microsoft.AspNetCore.Razor.Tasks.DotNetToolTask.GenerateFullPathToTool()
在 Microsoft.Build.Utilities.ToolTask.ComputePathToTool() …58CB71A2-CEB8-4440-9E9E-07402CB850AF.NET必知的EventCounters性能指标监视器2020-11-14T03:03:26Z2020-11-14T03:03:26ZHueiFeng695979933@qq.com在.NET我们对于性能指标监控,其实常见的有两个方法,一个是CLI工具dotnet-counters而另一个是代码级别的EventListener.
使用dotnet-counters
dotnet-counters是一个性能指标监视工具,用于临时运行状态监视和初级性能调查。它可以观察通过 EventCounter API发布的性能计数器值。例如,可以快速监视 CPU 使用情况或 .NET Core 应用程序中引发的异常率,以了解在使用 PerfView 或 dotnet-trace 深入调查更严重的性能问题之前是否有任何可疑操作。
-- 摘自 dotnet-counters
命令
dotnet-counters collect
dotnet-counters list
dotnet-counters monitor
dotnet-counters ps
安装dotnet- …9E7EEDF8-5DF9-4154-9647-FB713BB839ADAzure Storage Account 误删恢复2020-11-12T05:07:10Z2020-11-12T05:07:10ZHueiFeng695979933@qq.com登陆Azure站点,导航到新支持请求工作流程中
file
新建一个支持请求,信息可以按照如下这么去设置,当然要注意订阅账号别选择错
file
点击图中圈起来的链接“恢复删除的存储帐户”
file
请选择已删除的帐户, 并且单击恢复。
file
恢复完成后,我们会看到一个通知success~,恢复成功
file
737F4DF2-11C3-4A15-8FC1-846DC0C8BE65【Azure DevOps系列】Azure DevOps多阶段构建2020-10-28T01:43:10Z2020-10-28T01:43:10ZHueiFeng695979933@qq.com对于阶段的流水线其实是特别有用的,我们可以将构建、测试、或者说部署分为多个阶段进行处理。将您的应用程序部署到多个环境中,并从一个环境逐步过渡到另一个环境。例如,可以在CI中运行单元测试后自动部署到Dev环境,然后部署到运行集成测试的Test环境,然后手动部署到Production。
管道任务
这是一个最基础的管道任务,它在Microsoft托管代理上运行,同时他它采用ubuntu-16.04虚拟机镜像,执行后将会输出Hello world
pool:
vmImage: 'ubuntu-16.04'
steps:
- bash: echo Hello world
当然我们可以对此进行修改成如下方式:
jobs:
- job: myJob
timeoutInMinutes: 10
pool:
vmImage: 'ubuntu-16.04'
steps:
- …