- 博客(156)
- 资源 (4)
- 收藏
- 关注
原创 记一次与DeepSeek关于AI的对话
本文探讨了在虚拟世界中如何模拟现实中的感知机制。作者分析指出,现实世界中人获取信息主要通过事件驱动与轮询的混合模式,而游戏开发中通常采用事件驱动架构。针对去中心化虚拟世界的构建,提出了将声音、光线等建模为独立实体,通过物理引擎模拟传播和交互的方法。文章还讨论了如何在虚拟世界中实现自主探索,建议建立客观的物理层基础设施,赋予Agent传感器和决策能力,使程序员角色从"造物主"转变为"立法者",仅制定基础规则而非干预个体行为。这种设计既保持了世界的客观性,又保证了Agen
2025-09-02 18:13:56
1210
原创 C#项目上传git常见的忽略项目和推荐配置
本文总结了.NET项目中需要忽略提交的8类文件目录:1)编译生成和临时文件(如bin/、obj/);2)依赖项目录(如packages/);3)用户特定文件(如IDE配置文件);4)日志和运行时文件;5)测试相关文件;6)发布目录;7)包含敏感信息的文件;8)其他IDE临时文件。这些文件或目录建议通过.gitignore配置排除,避免将自动生成、本地配置或敏感信息提交到版本控制系统。
2025-08-11 17:15:11
594
原创 C# WaitHandle类的几个有用的函数
摘要:本文介绍了.NET中WaitHandle类的三种关键同步方法。WaitAny允许线程等待多个同步对象中的任意一个触发,返回触发对象的索引;WaitAll要求所有指定对象都触发才继续执行,适合多任务同步场景;SignalAndWait则原子性地执行"发出信号+等待"两步操作,常用于线程间精确协调。这三种方法都支持超时控制,可处理不同类型的同步对象(如Mutex、Semaphore等),是多线程编程中解决复杂同步问题的重要工具。使用时需注意线程限制和潜在死锁风险。
2025-08-05 13:56:04
964
原创 C# 线程同步(四)事件等待句柄——Event Wait Handle
本文系统介绍了.NET中的线程同步信号构造,重点对比了AutoResetEvent、ManualResetEvent、CountdownEvent和EventWaitHandle四种核心组件。AutoResetEvent通过自动重置机制实现单次线程通知,ManualResetEvent则允许广播式通知,CountdownEvent专为多线程协同设计,EventWaitHandle作为基础类支持跨进程同步。文章详细解析了各构造的适用场景、性能差异及典型应用模式,包括生产者-消费者模型和双向信号传递,并展示了线
2025-08-05 11:18:57
1392
原创 C#线程同步(三)线程安全
本文系统探讨了.NET中的线程安全实现策略。主要内容包括:1.线程安全基础概念,指出完全线程安全实现的高成本和性能损耗;2.NET框架类型的线程安全特性,强调静态成员线程安全而实例成员非线程安全的原则;3.应用服务中的线程安全实践,重点分析无状态设计和服务端缓存的实现方案;4.UI程序的线程管理模型,阐述WPF/WinForms的线程关联性特点和跨线程访问机制;5.不可变对象的线程安全优势,介绍如何通过不可变性简化多线程编程。文章提供了从基础理论到实际应用场景的完整线程安全解决方案,并特别指出了.NET 4
2025-08-01 18:44:27
1122
原创 C#线程同步(二)锁
本文系统介绍了C#中线程同步的几种核心机制:1)lock关键字及其底层Monitor实现,包括异常处理改进;2)同步对象的选择原则与注意事项;3)锁的使用时机、原子性保证和嵌套锁特性;4)死锁成因与防范策略;5)锁的性能影响与优化建议;6)跨进程同步的Mutex机制;7)控制并发度的Semaphore。重点强调了线程安全的基本原则、常见陷阱及最佳实践,为开发者构建健壮的多线程应用提供了全面指导。
2025-08-01 17:32:52
1439
原创 C# 线程同步(一)同步概念介绍
本文介绍了线程同步的核心概念与机制。首先阐述了线程阻塞的概念,即线程暂停执行时释放CPU资源的状态,并分析了四种解除阻塞的方式。其次对比了阻塞等待与轮询等待两种同步策略,指出阻塞等待更高效但轮询适合微秒级场景。文章还详细讲解了通过ThreadState属性检测线程状态的实用方法,强调其仅适用于诊断而非同步控制。全文系统梳理了线程同步的四大类别:简单阻塞方法、锁定构造、信号机制和非阻塞同步,为理解多线程编程中的同步问题提供了清晰框架。
2025-07-03 19:40:31
870
原创 C# 多线程(三)线程池
每当启动一个新线程时,系统都需要花费数百微秒来分配资源,例如创建独立的局部变量栈空间。默认情况下,每个线程还会占用约1MB内存。线程池通过共享和回收线程来消除这些开销,使得多线程技术可以应用于非常细粒度的场景而不会造成性能损失。这在利用多核处理器以"分而治之"方式并行执行计算密集型代码时尤为有用。。一旦达到限制,新任务将进入队列,只有当前线程完成任务后才能启动。这使得高并发应用(如Web服务器)的实现成为可能。(异步方法模式是一种更高级的技术,它能更高效地利用线程池中的线程,我们会在后面文章讲解)。
2025-07-02 14:53:48
1361
原创 C# 多线程(二)创建和启动线程
本文介绍了C#多线程编程中的关键知识点:1. 参数传递的两种方式(lambda表达式和ParameterizedThreadStart),并指出lambda捕获变量的注意事项;2. 线程命名对调试的帮助;3. 前台/后台线程的区别,后台线程在程序退出时会被强制终止;4. 线程优先级设置及其局限性;5. 多线程中的异常处理机制,强调必须在每个线程入口处单独处理异常。文章还提供了线程创建的基本示例和常见问题的解决方案,为C#多线程开发提供了实用指导。
2025-07-02 10:47:59
1285
原创 C# 多线程(一)基础概念
需要注意的是,线程调度和切换(当活跃线程数量超过CPU核心数时)会带来资源和CPU开销,同时线程的创建和销毁也需要成本。因此,应当尽可能减少线程交互,坚持使用简单可靠的设计方案。不同进程之间完全隔离,而线程的隔离程度则较为有限——具体来说,同一应用程序中的线程会共享(堆)内存。这也正是线程的价值所在:例如,一个线程可以在后台获取数据,而另一个线程则能实时显示接收到的数据。线程调度器确保所有活动线程都能分配到适当的执行时间,同时保证处于等待或阻塞状态(例如在独占锁或用户输入上)的线程不会消耗CPU时间。
2025-07-01 16:25:40
1025
原创 C# AOP编程
C#中的AOP(面向切面编程)框架主要分为编译时织入和动态代理两大类。编译时织入框架如PostSharp和AspectInjector,在编译时将切面代码织入目标方法,运行时性能较好,但可能增加编译时间。动态代理框架如Autofac,通过拦截器在运行时动态插入切面代码,适合高频调用场景,但可能带来额外性能开销。文章通过AspectInjector和Autofac的示例,展示了如何在方法执行前后插入日志记录代码,分别演示了编译时织入和动态代理的实现方式。
2025-05-21 19:45:43
868
原创 C#在函数执行前插入代码的办法
本文介绍了在C#中不修改原函数代码的情况下插入额外执行逻辑的三种方法:1) 装饰器模式,通过包装类在执行前后添加代码;2) 事件机制,需在函数内部预置事件触发点;3) AOP框架(如PostSharp),可动态注入代码。其中装饰器模式需额外编码但思路直观,事件机制需要预先设计,AOP最为灵活但依赖特定框架。三种方法各有优缺点,可根据实际需求选择使用。<|end▁of▁sentence|>
2025-05-21 15:41:19
410
翻译 C# 中的IEnumerable、IList和IReadOnlyList 的区别
简单点说就是IEnumrable是所有可迭代集合最基本的通用接口,如果函数传入的参数是IEnumerable类型,那么不要试图去修改该集合中的元素。IList可以认为是List类型的特有功能的接口,你传入IList和List类型做参数,基本上是等价的,可遍历,也可以修改。IReadOnlyList的功能和IList类似,除了不能修改集合中的元素,其它都可以。
2025-05-06 11:57:33
334
原创 C# 利用ssh 开启一个命令交互窗口
需要说明的是,为了避免输入输出相互阻塞,这里读取输出采用另一个线程执行。本文记录C#如何利用ssh远程连接服务器,并开启一个命令交互窗口。
2025-01-23 11:32:53
725
原创 从N个数中均匀随机采样M个数
目录一.背景二. 问题分析1.从抽样分析2.从等概率分析三.代码实现四. 算法优化一.背景 最近在做多传感器数据同步的时候遇到一个问题,多个传感器采集数据的频率可能时不一样的,但是数据需要对齐,这样才能进行融合训练。我的一个简单思路就是将同一秒的数据以采样频率最低的数据为标准对齐,那么这必然涉及到对频率高的数据进行采样。为了保证采样尽可能的均匀,不至于,相同序列的帧在时间上不至于一样太大差距,所以希望能有一个实验均匀采样。二. 问题分析1
2024-12-27 15:51:11
1141
原创 Kaggle 数据集dogs-vs-cats的错误
预览一下这两个数据,大概率无法显示。删掉这两个数据可能你的模型就可以跑起来了。如果遇到错误图像,则会暂停运行并显示错误的文件名。
2024-10-26 19:45:57
496
原创 广度优先搜索Breadth-First-Search
广度优先搜索总是能找到一个动作最少的解,因为当他生成深度为d的节点时,说明已经生成了升读为d-1的所有节点,如果其中一个节点是解,它应该已经被找到了,这对于所有动作都具有相同代价的问题,它是代价最优的,但对于不具有该特性的问题,则不一定是最优的。广度优先搜索,稍微学过算法的人都知道,网上也一大堆资料,这里就不做过多介绍了。问题来了,我们这次还是没确定从起点到目标点的最短路径,因为没有用到距离信息,别急,下一节DijkStra算法来帮我们彻底解决这个问题。,这样的指数级上界是可怕的,举个例子:假设。
2024-09-07 11:25:03
922
原创 最佳优先搜索best-find search
算法每次选取最近的节点,因此我们没有得到最优解,要想得到最优解,需要对算法进行改造,使之称为启发式算法,我会在后续章节介绍一二。,其中n是节点的总数。这里只选取到BuCharest城市的数据,该城市是访问Urziceni和Giurgiu后续的点必经之路。显然上面的BFS是一种贪婪算法,每次选取最优的近邻点是一种“短视”,虽然如此,他仍是一种可行的算法。如果你熟悉广度优先搜索,那么上面的代码也没什么难度。算法的性能显然与我们选择什么样的代价函数有直接关系。最佳优先搜索的算法可以参考。该算法最坏的复杂度是。
2024-09-05 17:01:47
1041
原创 C#中值类型与引用类型的存储
请记住一个引用类型,其实例数据部分始终存放在堆里,既然两个成员都是对象数据的一部分,那么他们都会被存放在堆里,无论他们诗值类型还是引用类型。记住上面的两张图,搞不清楚时,自己划一下,以后分析值对象和引用对象在内存的位置就心里有数了。首先,构造student对象用了new,所以student的实例数据存储在堆上,其引用部分放在堆里。C#中类型分为两种:值类型和引用类型,这两种类型的对象在内存中的存储方式不同。如果存储了一个对象,该对象有多个成员,成员既有值对象又有引用对象时,存储情况如何呢?
2024-04-02 20:53:36
903
原创 C# 取消一个不带CancellationToken的任务?
在异步函数中,一般使用CancellationToken来控制函数的执行。那么如果一个异步函数没有这个Token参数,如何取消呢?
2023-10-18 18:08:03
694
翻译 C#中的TaskCompletionSource
在C#异步编程中使用await/async时,会经常使用Task类,除了void之外,Task是异步方法的主要返回类型,还有后来的TaskValue(较少使用)。那偶尔也会看见异步中使用TaskCompletionSource,它有什么用呢?
2023-10-18 16:40:21
2813
原创 C# 通过回调获取多线程中的结果
答案是传递一个回调函数。看具体的例子,假设我有一个求自然数的累加和函数,我想让一个线程单独运行,且返回结果。在C#中多线程运行一旦开启,是没办直接返回你要的结果的,但有时候我们确实需要线程给我们结果要怎么做呢?这个类不仅接受参数Number,还接受一个回调函数:Action.在计算完成前将结果传递给回调函数。这里只是简单地打印,事实上还可以将取值拿出来,做法类似于上一节提到的。
2023-10-13 12:10:52
816
原创 C# 往多线程传递安全参数的方法
这样,在执行时,我们向多线程传递的是类PassParameter。sToThread的成员函数,且没有任何参数。这样就实现了安全的将参数传递到线程中。为此要如何避免这种问题呢?
2023-10-13 11:41:30
582
原创 C#关于接口的常见面试问题
1. C# 中的接口是一个完全未实现的类,用于声明对象的一组方法。因此,我们可以将接口定义为纯抽象类,它允许我们仅定义抽象方法。抽象方法是指没有主体或实现的方法。2. 一个类可以从另一个类继承,也可以从接口继承。所以,继承可以分为两类:实现继承和接口继承。3. C#不支持多重继承,接口可以弥补这一缺陷。4. 不行,默认情况下,.NET 接口方法是隐式公共的,即使它们属于嵌套接口。非公共修饰符对于接口方法无效。因此,在这种情况下,编译器将失败并警告您。5. 不可以。
2023-10-12 16:17:56
525
1
原创 数学计算式转为表达式树
数据结构“栈”的一个用途就是:平衡符号,比如这样一个代数式:(a(b+c)*a(e*f+a*(c+d))),你能一眼看出这个式子的括号是否正确吗?更何况还可以加入中括号([]),大括号({})。如果写一个算法来验证这个式子的话,利用栈这种数据结果是最方便的:构造一个空栈,读入字符串直到文件尾。如果字符是一个开放符号,则将其推入栈中,如果字符是一个封闭符号,则房栈空时报错;否则将栈元素弹出。如果弹出的符号不是对应的开放符号,则报错。在文件尾,如果栈非空则报错。
2023-09-07 10:35:45
868
原创 C# 泛型集合中的排序
就算不熟悉Linq,熟悉SQL查询语句的,也能很快上手Linq。List类的Sort方法有4个重载,其中一个是Sort(IComparer comparer),也就是你可以直接传入一个实现ICompare的对象,Sort方法会调用次对象的固定方法,这里我们将这个特殊的对象叫做。从前面的讨论可以看出最简单的排序方法是利用Linq或者Lambda,另外两种会增加额外的代码量,但是我们应该了解其背后的原理,Linq和Lambda都是C#后面陆续推出的,自然会更能节省开发者时间。
2023-02-13 17:51:25
1473
原创 再说多线程(五)——死锁
在前面四节中,我们一直没有讨论多线程程序的一个负面问题——死锁,有了一定的基础,现在是时候研究一下死锁了。死锁一定是出现在多线程程序中,单线程是不可能造成死锁的,因为你不可能同时加两把锁。死锁有个简单的例子,假设你和你的邻居关系很好,你们相互放了一把备用钥匙在对方家里,一般来说,只要有一个人带了钥匙,那两个人一定可以各回各家,但是恰好有一天,两人出门都忘记带钥匙,回家时发现对方在门口等着,两个人只能干瞪眼。这就是死锁。
2023-01-13 16:40:00
805
翻译 再说多线程(四)——Semaphore类
C#中的信号量类用于限制可以同时访问共享资源的外部线程的数量。换句话说,我们可以说Semaphore允许一个或多个外部线程进入临界区并在线程安全的情况下并发执行任务。因此,在实时情况下,当我们的资源数量有限并且我们想限制可以使用它的线程数量时,我们需要使用信号量。
2023-01-13 11:15:20
993
翻译 再说多线程(三)——Mutex类
在前面2节,我们已经讨论了Lock语句和Monitor类,Locks 和 Monitors 确保 InProcess 线程的线程安全,即由应用程序本身生成的线程,即内部线程。但是,如果线程来自 OutProcess,即来自外部应用程序,那么 Locks 和 Monitors 将无法控制它们。而 Mutex 确保进程外线程的线程安全,即由外部应用程序生成的线程,即外部线程。可能前面一段是说的不是很明白,什么是内部进程和外部进程呢?让我们首先创建一个控制台应用程序,然后将以下代码复制并粘贴到其中。
2023-01-13 09:29:15
1585
2
原创 再说多线程(二)——细说Monitor类
1. Monitor.Wait 方法有两个比较常用的方法重载:Object:等待的锁的对象功能:释放当前线程所占用的对象锁,并且阻塞当前的线程直到它再次拥有这个锁。- Object:等待的锁的对象- Int32:线程再次进入就绪队列的等待时长,单位毫秒功能:释放当前线程所占用的对象锁,并且阻塞当前的线程直到它再次拥有这个锁。如果指定的时长过去,线程将由等待队列转移到就绪队列。2. Monitor.Wait 方法的主要执行步骤阻塞当前的线程将这个线程移动到等待队列中释放当前的同步锁。
2023-01-12 14:09:38
1440
原创 再说多线程(一)
世界是并行!做过复杂项目的朋友一定遇到过并发的问题,无论是大项目如订票系统,还是小项目中的文件管理都会有并行需求。所以不同于上学时接触的大部分代码,实际的业务往往是为多人提供服务,必然天然的带有并发的需求。这里我先不解释并行和并发的区别,也不去讨论cpu和操作系统的低层是如何做到并发的,让我们从最简单的串行说起。一个简单的打印函数,只不过,在两句话之间,添加了一个小停顿。
2023-01-11 16:30:38
477
原创 关于枚举类(Enumeration Class )
在微软的微服务架构案例eshopOnContainer中,对于订单的状态是这样的: 微软没有直接使用传统的Enum关键字,而是自定了以一个抽象类:Enumeration。最开始,我有些不解,为什么么要“舍近求远”?其实微软官方在此文中提到了枚举类,理由是启动面向对象语言的所有丰富功能。解释的很晦涩,虽然给出了代码案例,但是还是让人很难体会到其中奥妙。直到最近又看了这个博客,似乎才深入理解了一些。结合一个例子说明,可能更好! 假设你要去买咖啡,正常情况下会有“大、中、小”三种
2022-12-06 01:45:39
1190
原创 关于架构的一些理念
软件的需求是不断变更的,软件的升级也是必然的,因此我们应该再进行架构设计的时候,避免后续软件需求变更,导致软件退化,并且在软件的升级过程中,我们要适时的进行架构的升级,以保持高质量的软件设计。如果我们每次软件升级的时候,没有及时的调整程序结构,而是在原有的程序结构上不断的加入代码,最终的软件就会退化。他分为战略设计和战术设计两个层次:DDD的战略设计可以帮助公司的领导人进行团队的划分,人员的组织,产品线的规划,也可以帮助产品经理对产品功能进行规划,还可以帮助架构师进行项目架构的规划,术站的选择等;
2022-11-17 15:13:39
1149
原创 Fluent Facede Pattern(外观模式)
外观模式的用意是为子系统提供一个集中化和简化的沟通渠道,而不是向子系统加入新的行为,新的行为的增加应该通过修改原有子系统类或增加新的子系统类来实现,不能通过外观类来实现。现代的软件系统都非常复杂,尽管我们已经想尽一切方法将其“分而治之”,把一个系统划分为好几个较小的子系统了,但是仍然可能会存在这样的问题:子系统内有非常多的类,客户端往往需要和许多对象打交道之后 才能完成想要完成的功能。接下来我们定义Car的外观,我们将外观定义放在两类中,一类定义颜色,品牌,门数,一类定义生产城市地址。
2022-11-11 16:45:53
581
原创 递归泛型(recursive generic)
原因很简单,SetName函数返回的对象类型是EmployeeInfoBuilder,无法调用EmployeePositionBuilder类的函数成员。当然我们可以将Employee对象以构造注入的方式传入进去,但是这样就违背了我们的Fluent原则。稍微说明一下的就是,这么做一方面是不好理解,另一方面可能对性能有一定的影响,我认为这个派生链条不宜过长,希望有懂的朋友可以指点一下。对于上面两个泛型类,我们无法直接定义,只能借助更高层次的派生类构造,且这个类不能再是泛型,也就是泛型链的终点。
2022-11-11 11:48:27
713
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅