目标: 在运行 HarmonyOS Next 的华为 MateBook Pro 上侧载安装第三方应用程序。
注:本教程同样适用于在运行 HarmonyOS Next 的华为手机上侧载安装第三方应用程序。
所需准备
一台运行 HarmonyOS Next 的华为 MateBook Pro。
一台 Windows 电脑。
一根数据线:
USB-A to Type-C
或 Type-C to Type-C (确保能将两台电脑连接)。
网络连接:两台电脑需在同一局域网下(用于无线调试连接)。
步骤详解
第一步:鸿蒙 PC (MateBook Pro) 端设置 (启用开发者模式与调试)
连接设备: 使用数据线将鸿蒙 MateBook Pro 连接到 Windows 电脑。
打开设置: 在鸿蒙 PC 上,进入
设置
。进入关于本机: 在设置中,找到并点击
关于本机
或您的电脑型号
。启用开发者模式:
在“关于本机”界面,找到
软件版本
或HarmonyOS 版本
。连续点击
软件版本/HarmonyOS 版本
文字 5 次以上。系统会提示“您已处于开发者模式”或提示重启进入开发者模式。按提示重启电脑(如果需要)。
打开开发者选项:
重启后,回到
设置
->系统
->开发者选项
(路径可能略有不同,在“系统和更新”或“隐私与安全”下查找)。启用 USB 调试:
在开发者选项中,找到
USB 调试
,将其开启。首次开启时,可能会弹出提示(连接线后或稍后操作时),点击
允许
。注意提示:系统可能提示“Matebook Pro 上的右上角的 Type-C 口可以进行调试”,确保使用正确的接口连接调试线。如果弹出“始终允许本机调试”选项,勾选并允许。
启用并记录无线调试信息:
在开发者选项中,找到
无线调试
,将其开启。开启后,系统会显示一个 IP 地址和端口号(例如
192.168.x.x:xxxxx
)。务必准确记下这个 IP 地址和端口号,后续在 Windows 端连接时必须用到。至此,鸿蒙 PC 端的准备工作完成。
第二步:Windows 电脑端操作 (使用小白调试助手)
获取工具和 HAP 包:
访问包含 HarmonyOS Next 可用 HAP 包的资源(如 GitHub 上的相关仓库,搜索 “HarmonyOS Next HAP”)。
下载小白调试助手:
在工具仓库中找到
小白调试助手
或类似名称。点击
Latest
(最新版本)。点击
Download
下载其 Windows 版压缩包(.zip
文件)。下载目标应用的 HAP 包(以 ClashBox 为例,你也可以使用自己已有的 .hap 文件):
在应用仓库中找到
ClashBox
。同样点击
Latest
->Download
下载其 HAP 包(.hap
文件)。准备小白调试助手:
将下载的小白调试助手压缩包解压到一个非中文且无空格路径的文件夹。
进入解压后的文件夹,找到可执行文件。双击运行。根据 Windows SmartScreen 或安全软件提示(若有),选择
更多信息
->仍要运行
。登录华为开发者账号 (强烈推荐):
在小白调试助手界面,找到登录入口(通常在界面顶部或设置中),点击
登录
。使用您的华为开发者账号登录(登录时,您的华为手机可能会收到验证码,或在鸿蒙PC上验证)。
输入验证码,并在授权请求页面点击
允许
。登录成功后,界面通常会显示您的账号昵称或ID。重要: 开发者账号签发的应用证书有效期通常为 6 个月,普通账号仅 14 天。为方便使用,建议申请华为开发者账号。
连接鸿蒙设备:
在小白调试助手主界面,找到
连接设备
、添加设备
或类似功能的按钮并点击。在弹出的连接窗口(通常是输入IP和端口的对话框)中:
输入您在鸿蒙 PC 上
无线调试
功能中记录的 IP 地址。输入记录的 端口号。
点击
确定
、连接
或OK
。连接成功:如果地址和端口输入正确,且鸿蒙 PC 的开发者选项已开启无线调试:
鸿蒙 PC 可能弹出调试请求(“允许调试?”),勾选“始终允许”并点击
允许
。小白调试助手界面会显示“连接成功”或目标设备信息。
(若未弹出提示框但连接成功,也属正常)
第三步:安装第三方 HAP 包
选择 HAP 包:
确保设备已连接成功。
在小白调试助手界面,找到
选择 HAP
、加载 HAP
、安装应用
或类似按钮(通常在文件菜单或主功能区)。点击该按钮,浏览文件系统,找到您下载好的目标 HAP 文件(如
ClashBox-xxx.hap
),选中并点击打开
。开始安装:
选择好 HAP 文件后,小白调试助手界面通常会激活
开始调试
、安装
或运行
按钮。点击
开始调试
或安装
。等待安装完成:
小白调试助手会开始处理 HAP 包:进行签名、推送到设备并安装。
观察进度条或日志输出,耐心等待直至提示“安装成功”。
第四步:在鸿蒙 PC 上使用安装的应用
安装完成后,返回您的鸿蒙 MateBook Pro。
在桌面或
开始菜单
中,查找您刚刚安装的应用图标(如ClashBox
)。点击图标即可启动使用该应用。
常见问题处理
签名错误/证书问题:在小白调试助手内寻找 **
清理缓存
、重置证书
、重新登录
** 或类似选项。执行后,重新登录开发者账号,再尝试安装。确保登录的是开发者账号。Java 环境报错:如果小白调试助手提示需要 Java 环境(如
java
命令未找到),按照其提示点击安装,它会引导下载并安装所需的 Java Runtime Environment (JRE)。连接失败:
检查鸿蒙 PC 的
无线调试
IP 和端口号是否变化(息屏、重启、网络切换可能导致变化),在开发者选项里重新确认并输入。确保两台电脑在同一局域网。
检查鸿蒙 PC 的 **
USB 调试
和无线调试
是否已开启**。尝试在鸿蒙 PC 的开发者选项中关闭再重新开启
无线调试
,获取新的端口号。其他报错:查阅小白调试助手官方的使用说明或 GitHub 仓库的 Issue 区寻求解决方案。

IIS 中使用 HttpPlatformHandler 模块部署 python web 项目时遇到 502.3 网关错误:
HTTP 错误 502.3 - Bad Gateway
There was a connection error while trying to route the request.
最可能的原因:
CGI 应用程序没有返回一组有效的 HTTP 错误。
由于父网关中出现错误,充当代理或网关的服务器无法处理该请求。
可尝试的操作:
使用 DebugDiag 排查 CGI 应用程序。
确定此错误是否由代理或网关引起。
详细错误信息:
模块 httpPlatformHandler
通知 ExecuteRequestHandler
处理程序 httpplatformhandler
错误代码 见下方表格
详细信息:
当 CGI 应用程序未返回一组有效的 HTTP 头,或者代理或网关无法将请求发送至父网关时,便会出现此错误。您可能需要获取一个网络跟踪,或者与代理服务器管理员联系(如果不是 CGI 的问题)。
错误代码 | 可能的错误原因 |
---|---|
0x8007053d | 未安装相关组件库,建议执行命令:pip install -r requirements.txt |
0x80070005 | 若显示配置错误“由于权限不足而无法读取配置文件”则是应用代码目录未配置相应用户的读取权限; 访问受限,请正确配置 IIS 中的网站凭据、应用程序池标识、项目目录“读取”、解释器目录“读取和执行”权限等 |
0x80072ee2 | 执行超时,一般发生在批量读写的时候 |


安装 PyPI(包/库/组件):
pip install 包名
如果安装失败,尝试用国内镜像
pip install 包名 -i https://pypi.tuna.tsinghua.edu.cn/simple
如果不想每次都加 -i 参数,可以更改全局配置
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
查看所有配置
pip config list
查看 python 文件路径
# Windows 或 Linux 通用
python -c "import sys; print(sys.executable)"
默认路径为:C:\Users\<user name>\AppData\Local\Programs\Python\Python<version>\python.exe
常用组件介绍
包名 | 介绍 |
---|---|
Flask | 一款基于 Python 的轻量级 Web 开发框架 |
Django | 一款基于 Python 的重量级 Web 开发框架 |
Pandas | 一个数据分析包,提供 Series、Time-Series、DataFrame、Panel、Panel4D、PanelND 等数据结构 |
更多

临界区与 lock 关键字
核心作用:
通过将多线程访问串行化,保护共享资源或代码段。lock 关键字是 Monitor 类的语法糖,提供异常安全的临界区实现。
实现示例:
// 创建私有静态只读对象 // private static readonly object _lockObj = new object(); private static readonly System.Threading.Lock _locker = new(); // .NET 9+ 推荐使用 Lock 类型,避免传统 object 的性能损耗 public void ThreadSafeMethod() { lock (_lockObj) { // 临界区代码(每次仅一个线程可进入) } }
超时机制:
高并发场景可结合 Monitor.TryEnter 设置超时,避免无限等待:
if (Monitor.TryEnter(lockObject, TimeSpan.FromSeconds(1))) { try { /* 操作 */ } finally { Monitor.Exit(lockObject); } }
关键特性:
用户态锁(无内核切换开销)
自动调用Monitor.Enter和Monitor.Exit
必须使用专用私有对象作为锁标识
注意事项:
❌ 避免锁定this、Type实例或字符串(易引发死锁)
❌ 避免嵌套锁(需严格按顺序释放)
✅ 推荐readonly修饰锁对象
❌ lock 不适用于异步代码(async/await),需使用 SemaphoreSlim 实现异步锁
互斥锁(Mutex)
核心作用:
系统级内核锁,支持跨进程同步,但性能开销较高(用户态/内核态切换)。
实现示例:
using var mutex = new Mutex(false, "Global\\MyAppMutex"); try { // 等待锁(最大等待时间500ms) if (mutex.WaitOne(500)) { // 临界区代码 } } finally { if (mutex != null) { mutex.ReleaseMutex(); } }
关键特性:
支持跨应用程序域同步
线程终止时自动释放锁
支持命名互斥体(系统全局可见)
适用场景:
单实例应用程序控制
进程间共享文件访问
硬件设备独占访问
信号量(Semaphore)
核心作用:
通过许可计数器控制并发线程数,SemaphoreSlim为轻量级版本(用户态实现)。
实现对比:
类型 跨进程 性能 最大许可数 Semaphore ✔️ 低 系统限制 SemaphoreSlim ❌ 高 Int32.Max 代码示例:
// 创建初始3许可、最大5许可的信号量 var semaphore = new SemaphoreSlim(3, 5); semaphore.Wait(); // 获取许可 try { // 资源访问代码 } finally { semaphore.Release(); }
异步编程
private readonly SemaphoreSlim _asyncLock = new(1, 1); public async Task UpdateAsync() { await _asyncLock.WaitAsync(); try { /* 异步操作 */ } finally { _asyncLock.Release(); } }
典型应用:
数据库连接池(限制最大连接数)
API 请求限流
批量任务并发控制
事件(Event)
核心机制:
通过信号机制实现线程间通知,分为两种类型:
类型 信号重置方式 唤醒线程数 AutoResetEvent 自动 单个 ManualResetEvent 手动 所有 使用示例:
var autoEvent = new AutoResetEvent(false); // 等待线程 Task.Run(() => { autoEvent.WaitOne(); // 收到信号后执行 }); // 信号发送线程 autoEvent.Set(); // 唤醒一个等待线程
高级用法:
配合WaitHandle.WaitAll实现多事件等待
使用ManualResetEventSlim提升性能
读写锁(ReaderWriterLockSlim)
核心优势:
实现读写分离的并发策略,适合读多写少场景(如缓存系统)。
锁模式对比:
模式 并发性 升级支持 读模式(EnterReadLock) 多线程并发读 ❌ 写模式(EnterWriteLock) 独占访问 ❌ 可升级模式 单线程读→写 ✔️ 代码示例:
var rwLock = new ReaderWriterLockSlim(); // 读操作 rwLock.EnterReadLock(); try { // 只读访问 } finally { rwLock.ExitReadLock(); } // 写操作 rwLock.EnterWriteLock(); try { // 排他写入 } finally { rwLock.ExitWriteLock(); }
最佳实践:
优先使用ReaderWriterLockSlim(旧版有死锁风险)
避免长时间持有读锁(可能饿死写线程)
原子操作(Interlocked)
原理:
通过CPU指令实现无锁线程安全操作。
常用方法:
int counter = 0; Interlocked.Increment(ref counter); // 原子递增 Interlocked.Decrement(ref counter); // 原子递减 Interlocked.CompareExchange(ref value, newVal, oldVal); // CAS操作
适用场景:
简单计数器
标志位状态切换
无锁数据结构实现
自旋锁(SpinLock)
核心特点:
通过忙等待(busy-wait)避免上下文切换,适用极短临界区(<1微秒)。
实现示例:
private SpinLock _spinLock = new SpinLock(); public void CriticalOperation() { bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); // 极短临界区代码 } finally { if (lockTaken) _spinLock.Exit(); } }
优化技巧:
单核CPU需调用Thread.SpinWait或Thread.Yield
配合SpinWait结构实现自适应等待
同步机制对比指南
机制 跨进程 开销级别 最佳适用场景 lock ❌ 低 通用临界区保护 Mutex ✔️ 高 进程间资源独占 Semaphore ✔️ 中 并发数限制(跨进程) SemaphoreSlim ❌ 低 并发数限制(进程内) ReaderWriterLockSlim ❌ 中 读多写少场景 SpinLock ❌ 极低 纳秒级临界区 Interlocked - 无锁 简单原子操作
选择原则:
优先考虑用户态锁(lock/SpinLock/SemaphoreSlim)
跨进程需求必须使用内核对象(Mutex/Semaphore)
读写比例超过10:1时考虑读写锁
自旋锁仅用于高频短操作(如链表指针修改)
通过以上结构化的分类和对比,开发者可以更精准地选择适合特定场景的线程同步方案。建议在实际使用中配合性能分析工具(如BenchmarkDotNet)进行量化验证。
💡 ASP.NET 的异步编程(async/await)本质是单进程内的线程调度,不算“跨进程”。每个 IIS 应用程序池对应一个独立的工作进程(w3wp.exe),不同用户访问同一应用程序池下的 ASP.NET 网站,两者的请求均由同一个 w3wp.exe 进程处理。可能跨进程的场景有:Web Garden 配置、多应用程序池部署等。
在 C# 中,除了常规锁机制(如 lock、Mutex、Semaphore 等),还有一些内置类型通过内部锁或无锁设计实现线程安全。以下是常见的几类:
线程安全集合(System.Collections.Concurrent)这些集合通过细粒度锁或无锁算法(如 CAS)实现线程安全,适合高并发场景。
ConcurrentDictionary:分段锁机制,将数据分片存储,每个分片独立加锁,减少锁竞争。
ConcurrentQueue / ConcurrentStack:基于原子操作(Interlocked)保证线程安全。
ConcurrentBag:每个线程维护本地存储,减少争用,适合频繁添加和移除的场景。
BlockingCollection:基于 ConcurrentQueue 和信号量(SemaphoreSlim)实现生产-消费者模式,支持阻塞和超时。
不可变集合(System.Collections.Immutable) 通过数据不可变性实现线程安全(无需锁),每次修改返回新对象。
Lazy 的线程安全初始化(Lazy<T>) 通过锁或 Interlocked 确保延迟初始化的线程安全。
通道(System.Threading.Channels)用于异步生产-消费者模型,内部通过锁和信号量管理容量限制。
内存缓存(System.Runtime.Caching.MemoryCache)内部使用锁保护共享状态,确保线程安全。
原子操作类型(Interlocked 类、Volatile 关键字、Unsafe 类)通过 CPU 指令实现无锁线程安全。
其他同步工具(Barrier、CountdownEvent)虽然不是严格意义上的锁,但用于协调线程。

在 .NET Framework 的缓存管理中,cacheMemoryLimitMegabytes 是一个关键配置属性,用于控制内存缓存(MemoryCache)实例的最大内存占用。以下是其具体用法及实现细节:
基本定义与作用
功能:通过 cacheMemoryLimitMegabytes 可设置 MemoryCache 实例允许占用的最大内存(单位:MB)。若缓存数据超过此限制,系统会自动淘汰旧条目。
默认值:默认值为 0,表示缓存基于计算机的物理内存自动管理(例如根据可用内存动态调整)。
配置方式
通过配置文件(web.config)
在 web.config 的 <system.runtime.caching> 节点下配置 namedCaches,示例:
<configuration> <system.runtime.caching> <memoryCache> <namedCaches> <add name="Default" cacheMemoryLimitMegabytes="500" physicalMemoryLimitPercentage="50" pollingInterval="00:05:00" /> </namedCaches> </memoryCache> </system.runtime.caching> </configuration>
参数说明:
cacheMemoryLimitMegabytes:最大内存限制(例如 500 表示 500MB)。
physicalMemoryLimitPercentage:允许使用的物理内存百分比(可选)。
pollingInterval:缓存清理策略的轮询间隔(例如每5分钟检查一次)。
通过代码动态配置
在初始化 MemoryCache 时,通过 NameValueCollection 传递参数:
var config = new NameValueCollection { { "cacheMemoryLimitMegabytes", "500" }, { "physicalMemoryLimitPercentage", "50" }, { "pollingInterval", "00:05:00" } }; var cache = new MemoryCache("CustomCache", config);
此方式适用于需要动态调整缓存策略的场景。
注意事项
优先级规则:
若同时配置了 cacheMemoryLimitMegabytes 和 physicalMemoryLimitPercentage,系统会选择两者中较小的值作为限制。
分布式缓存兼容性:
此属性仅适用于进程内缓存(如 MemoryCache),若使用 Redis 等分布式缓存需通过其独立配置管理内存。
监控与调试:
建议结合性能计数器(如 ASP.NET Applications 类别下的 Cache Total Entries)或日志记录模块(参考 web.config 的 <system.diagnostics> 配置)监控实际内存占用。
应用场景示例
场景:一个电商网站需要缓存商品目录数据,限制最大内存为 1GB。
配置实现:
<add name="ProductCatalogCache" cacheMemoryLimitMegabytes="1024" pollingInterval="00:10:00" />
代码调用:
var productCatalog = MemoryCache.Default["ProductCatalog"];
常见问题
Q:设置为 0 时缓存会无限制增长吗?
A:不会。此时缓存基于系统物理内存动态管理,通常上限为总内存的 70%-90%。
Q:如何验证配置已生效?
A:可通过 MemoryCache.GetCount() 统计条目数量,或使用性能监视器跟踪内存占用。

打开 .csproj 项目文件,在 <PropertyGroup> 标签内添加:
<Version>
1.0.$([System.Math]::Floor($([System.DateTime]::Now.Subtract($([System.DateTime]::Parse('2000-01-01T00:00:00Z'))).TotalDays))).$([MSBuild]::Divide($([System.Math]::Floor($([System.DateTime]::Now.TimeOfDay.TotalSeconds))), 2))
</Version>
最终生成的版本号示例: 1.0.9238.28518
其中,Major 与 Minor 是固定的,Build 是2000年1月1日至今的天数,Revision 是今天的秒数 / 2 所得的值。(为了防止数值超过 65535)
程序中获取版本号:
var version = Assembly.GetExecutingAssembly().GetName().Version!; // 当前类库
var version = Assembly.GetEntryAssembly()?.GetName().Version!; // 入口项目
从版本号获取发布时间:
DateTime versionTime = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);

在解决方案资源管理器中找到 Properties/AssemblyInfo.cs 文件。该文件存放程序集版本信息。
修改版本号格式
将以下代码片段中的 AssemblyVersion 改为使用星号通配符(建议保留主版本和次版本号):
[assembly: AssemblyVersion("1.0.*")] // 自动生成构建号和修订号 // [assembly: AssemblyFileVersion("1.0.0.0")] // 注释或删除此行
关闭确定性构建
用文本编辑器打开 .csproj 项目文件,在 <PropertyGroup> 标签内添加:
<Deterministic>false</Deterministic>
此设置允许 MSBuild 生成动态版本号。
最终生成的版本号示例: 1.0.9238.28518
其中,Major 与 Minor 是固定的,Build 是2000年1月1日至今的天数,Revision 是今天的秒数 / 2 所得的值。(为了防止数值超过 65535)
程序中获取版本号:
var version = Assembly.GetExecutingAssembly().GetName().Version;
从版本号获取发布时间:
DateTime versionTime = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);
查看 .NET Core / .NET 5+ 实现自动版本号的方法

命令提示符
打开记事本,粘贴下方命令,保存为 .bat 文件
@echo off iisreset pause
命令提示符(管理员)
打开记事本,粘贴下方命令,保存为 .bat 文件
@echo off if not "%1"=="admin" (powershell start -verb runas '%0' admin & exit) iisreset pause
PowerShell
创建一个快捷方式,目标为
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "Start-Process PowerShell -ArgumentList 'iisreset' -Verb RunAs"

大模型文件一般都比较大,Ollama 默认是下载到 C 盘的,如何更改到 D 盘或其它盘符中?
第一步,退出 Ollama。
第二步,设置环境变量,设置方法参这篇文章:
变量名:OLLAMA_MODELS
变量值:D:\.ollama\models(这是示例,填写自己的实际路径即可)
第三步,将默认路径下的 models 目录移至 D:\.ollama\
默认路径一般为 C:\Users\<用户>\.ollama\
