解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# è¿è¡Œæ—¶ä¿¡æ¯ Runtime
## 概述
`Runtime` 是 NewLife.Core ä¸çš„è¿è¡Œæ—¶ä¿¡æ¯å·¥å…·ç±»ï¼Œæä¾›å½“å‰è¿è¡ŒçŽ¯å¢ƒçš„å„ç§æ£€æµ‹å’Œæ“作功能。包括æ“作系统判æ–ã€çŽ¯å¢ƒå˜é‡è¯»å–ã€å†…å˜ç®¡ç†ã€è¿›ç¨‹ä¿¡æ¯ç‰åŠŸèƒ½ï¼Œæ˜¯è·¨å¹³å°å¼€å‘çš„é‡è¦åŸºç¡€ç»„件。
**命å空间**:`NewLife`
**文档地å€**:https://newlifex.com/core/runtime
## æ ¸å¿ƒç‰¹æ€§
- **平尿£€æµ‹**:Windowsã€Linuxã€OSXã€Monoã€Unity ç‰è¿è¡ŒçŽ¯å¢ƒè¯†åˆ«
- **环境判æ–**:控制å°ã€Webã€å®¹å™¨ç‰åº”用类型检测
- **高精度计时**:跨平å°çš„ `TickCount64` 实现,é¿å… 32 使º¢å‡º
- **内å˜ç®¡ç†**:GC 回收和工作集释放
- **环境å˜é‡**:ä¸åŒºåˆ†å¤§å°å†™çš„环境å˜é‡è¯»å–
## 快速开始
```csharp
using NewLife;
// åˆ¤æ–æ“作系统
if (Runtime.Windows)
Console.WriteLine("è¿è¡Œåœ¨ Windows 系统上");
else if (Runtime.Linux)
Console.WriteLine("è¿è¡Œåœ¨ Linux 系统上");
// 判æ–è¿è¡ŒçŽ¯å¢ƒ
if (Runtime.IsConsole)
Console.WriteLine("控制å°åº”用");
if (Runtime.Container)
Console.WriteLine("è¿è¡Œåœ¨å®¹å™¨ä¸");
// 获å–系统è¿è¡Œæ—¶é—´ï¼ˆæ¯«ç§’)
var uptime = Runtime.TickCount64;
Console.WriteLine($"系统已è¿è¡Œ {uptime / 1000 / 60} 分钟");
// 获å–当å‰è¿›ç¨‹ID
var pid = Runtime.ProcessId;
Console.WriteLine($"当å‰è¿›ç¨‹ID: {pid}");
// 释放内å˜
Runtime.FreeMemory();
```
## API å‚考
### 平尿£€æµ‹
#### Windows
```csharp
public static Boolean Windows { get; }
```
æ˜¯å¦ Windows æ“作系统。
**实现方å¼**:
- .NET Core/.NET 5+:使用 `RuntimeInformation.IsOSPlatform(OSPlatform.Windows)`
- .NET Framework:检查 `Environment.OSVersion.Platform`
**示例**:
```csharp
if (Runtime.Windows)
{
// Windows 特有的æ“作,如调用 Win32 API
Console.WriteLine("Windows 版本: " + Environment.OSVersion.VersionString);
}
```
#### Linux
```csharp
public static Boolean Linux { get; }
```
æ˜¯å¦ Linux æ“作系统。
**示例**:
```csharp
if (Runtime.Linux)
{
// Linux 特有的æ“ä½œï¼Œå¦‚è¯»å– /proc 文件系统
var cpuInfo = File.ReadAllText("/proc/cpuinfo");
}
```
#### OSX
```csharp
public static Boolean OSX { get; }
```
æ˜¯å¦ macOS æ“作系统。
#### Mono
```csharp
public static Boolean Mono { get; }
```
是å¦åœ¨ Mono è¿è¡Œæ—¶çŽ¯å¢ƒä¸è¿è¡Œã€‚通过检测 `Mono.Runtime` 类型是å¦å˜åœ¨æ¥åˆ¤æ–。
**应用场景**:
- æŸäº› API 在 Mono 下行为ä¸åŒ
- 针对 Mono 进行特殊优化或兼容处ç†
#### Unity
```csharp
public static Boolean Unity { get; }
```
是å¦åœ¨ Unity 引擎环境ä¸è¿è¡Œã€‚通过检测 `UnityEngine.Application` 类型是å¦å˜åœ¨æ¥åˆ¤æ–。
### 环境判æ–
#### IsConsole
```csharp
public static Boolean IsConsole { get; set; }
```
æ˜¯å¦æŽ§åˆ¶å°åº”用程åºã€‚
**判æ–逻辑**:
1. å°è¯•访问 `Console.ForegroundColor` è§¦å‘æŽ§åˆ¶å°å¯ç”¨æ€§æ£€æŸ¥
2. 检查当å‰è¿›ç¨‹æ˜¯å¦æœ‰ä¸»çª—å£å¥æŸ„
3. ä»»ä½•å¼‚å¸¸éƒ½è§†ä¸ºéžæŽ§åˆ¶å°çŽ¯å¢ƒ
**示例**:
```csharp
if (Runtime.IsConsole)
{
Console.WriteLine("这是控制å°åº”用,å¯ä»¥ä½¿ç”¨å½©è‰²è¾“出");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("绿色文本");
Console.ResetColor();
}
else
{
// GUI 应用或æœåŠ¡
Debug.WriteLine("éžæŽ§åˆ¶å°çŽ¯å¢ƒ");
}
```
> **注æ„**:å¯ä»¥é€šè¿‡è®¾ç½® `Runtime.IsConsole = false` 强制ç¦ç”¨æŽ§åˆ¶å°åˆ¤æ–。
#### Container
```csharp
public static Boolean Container { get; }
```
是å¦åœ¨ Docker/Kubernetes 容器ä¸è¿è¡Œã€‚通过检查环境å˜é‡ `DOTNET_RUNNING_IN_CONTAINER` æ¥åˆ¤æ–。
**示例**:
```csharp
if (Runtime.Container)
{
// 容器环境下的特殊处ç†
// 例如:使用容器内的é…置路径
var configPath = "/app/config";
}
```
#### IsWeb
```csharp
public static Boolean IsWeb { get; }
```
æ˜¯å¦ Web 应用程åºã€‚
**判æ–逻辑**:
- .NET Core/.NET 5+:检查是å¦åŠ è½½äº† `Microsoft.AspNetCore` 程åºé›†
- .NET Framework:检查 `System.Web.HttpRuntime.AppDomainAppId` æ˜¯å¦æœ‰å€¼
**示例**:
```csharp
if (Runtime.IsWeb)
{
// Web 应用特有的处ç†
// 例如:使用 HTTP 上下文相关功能
}
```
### 时间与计数
#### TickCount64
```csharp
public static Int64 TickCount64 { get; }
```
系统å¯åЍ以æ¥çš„æ¯«ç§’数(64ä½ï¼‰ï¼Œä¸ä¼šå‘生 32 使º¢å‡ºé—®é¢˜ã€‚
**实现方å¼**:
- .NET Core 3.1+:直接使用 `Environment.TickCount64`
- Windows 旧框架:调用 `GetTickCount64` Win32 API
- å…¶ä»–å¹³å°ï¼šä½¿ç”¨ `Stopwatch.GetTimestamp()` 计算,或回退到 `Environment.TickCount`
**应用场景**:
- 高精度计时
- 计算时间间隔
- é¿å… `Environment.TickCount` 约 49.7 天溢出的问题
**示例**:
```csharp
// æµ‹é‡æ“作耗时
var start = Runtime.TickCount64;
DoSomeWork();
var elapsed = Runtime.TickCount64 - start;
Console.WriteLine($"耗时: {elapsed} ms");
// 设置超时
var timeout = Runtime.TickCount64 + 5000; // 5ç§’åŽè¶…æ—¶
while (Runtime.TickCount64 < timeout)
{
if (CheckCondition()) break;
Thread.Sleep(100);
}
```
#### UtcNow
```csharp
public static DateTimeOffset UtcNow { get; }
```
获å–å½“å‰ UTC 时间。基于全局时间æä¾›è€…(`TimerScheduler.GlobalTimeProvider`),在星尘应用ä¸ä¼šå±è”½æœåŠ¡å™¨æ—¶é—´å·®ã€‚
**示例**:
```csharp
var utcNow = Runtime.UtcNow;
Console.WriteLine($"UTCæ—¶é—´: {utcNow}");
Console.WriteLine($"本地时间: {utcNow.LocalDateTime}");
```
### 进程信æ¯
#### ProcessId
```csharp
public static Int32 ProcessId { get; }
```
当å‰è¿›ç¨‹ ID。使用缓å˜é¿å…é‡å¤èŽ·å–。
**实现方å¼**:
- .NET 5+:使用 `Environment.ProcessId`
- 旧框架:使用 `Process.GetCurrentProcess().Id`
**示例**:
```csharp
Console.WriteLine($"当å‰è¿›ç¨‹ID: {Runtime.ProcessId}");
// 用于日志记录
var logPrefix = $"[PID:{Runtime.ProcessId}]";
```
#### ClientId
```csharp
public static String ClientId { get; }
```
å®¢æˆ·ç«¯æ ‡è¯†ï¼Œæ ¼å¼ä¸º `ip@pid`。用于分布å¼ç³»ç»Ÿä¸æ ‡è¯†å®¢æˆ·ç«¯å®žä¾‹ã€‚
**示例**:
```csharp
Console.WriteLine($"å®¢æˆ·ç«¯æ ‡è¯†: {Runtime.ClientId}");
// 输出类似: 192.168.1.100@12345
// 用于分布å¼é”ã€æ¶ˆæ¯é˜Ÿåˆ—æ¶ˆè´¹è€…æ ‡è¯†ç‰
var consumerId = Runtime.ClientId;
```
### 环境å˜é‡
#### GetEnvironmentVariable
```csharp
public static String? GetEnvironmentVariable(String variable)
```
获å–环境å˜é‡ï¼Œ**ä¸åŒºåˆ†å¤§å°å†™**。
**特点**:
- å…ˆå°è¯•精确匹é…
- 若未找到,é历所有环境å˜é‡è¿›è¡Œä¸åŒºåˆ†å¤§å°å†™çš„æ¯”较
**示例**:
```csharp
// ä¸åŒºåˆ†å¤§å°å†™èŽ·å–环境å˜é‡
var path = Runtime.GetEnvironmentVariable("PATH");
var home = Runtime.GetEnvironmentVariable("HOME");
var customVar = Runtime.GetEnvironmentVariable("MY_APP_CONFIG");
```
#### GetEnvironmentVariables
```csharp
public static IDictionary<String, String?> GetEnvironmentVariables()
```
èŽ·å–æ‰€æœ‰çŽ¯å¢ƒå˜é‡ï¼Œè¿”回ä¸åŒºåˆ†å¤§å°å†™çš„å—典。
**示例**:
```csharp
var envVars = Runtime.GetEnvironmentVariables();
foreach (var kv in envVars.Where(e => e.Key.StartsWith("DOTNET")))
{
Console.WriteLine($"{kv.Key} = {kv.Value}");
}
```
### é…ç½®
#### CreateConfigOnMissing
```csharp
public static Boolean CreateConfigOnMissing { get; set; }
```
é…置文件ä¸å˜åœ¨æ—¶ï¼Œæ˜¯å¦ç”Ÿæˆé»˜è®¤é…置文件。默认为 `true`。
**é…置方å¼**:
- 环境å˜é‡ï¼š`CreateConfigOnMissing=false`
- 代ç 设置:`Runtime.CreateConfigOnMissing = false`
**示例**:
```csharp
// ç”Ÿäº§çŽ¯å¢ƒç¦æ¢è‡ªåŠ¨åˆ›å»ºé…置文件
Runtime.CreateConfigOnMissing = false;
```
### 内å˜ç®¡ç†
#### FreeMemory
```csharp
public static Boolean FreeMemory(Int32 processId = 0, Boolean gc = true, Boolean workingSet = true)
```
释放内å˜ã€‚执行 GC 回收并释放工作集(Windows)。
**傿•°è¯´æ˜Ž**:
- `processId`ï¼šç›®æ ‡è¿›ç¨‹ID,0 表示当å‰è¿›ç¨‹
- `gc`ï¼šæ˜¯å¦æ‰§è¡Œ GC 回收(仅当å‰è¿›ç¨‹æœ‰æ•ˆï¼‰
- `workingSet`:是å¦é‡Šæ”¾å·¥ä½œé›†ï¼ˆä»… Windows 有效)
**执行æ¥éª¤**:
1. 执行 `GC.Collect` 进行垃圾回收
2. 调用 `GC.WaitForPendingFinalizers` ç‰å¾…终结器
3. 冿¬¡æ‰§è¡Œ `GC.Collect`
4. 调用 `EmptyWorkingSet` 释放工作集(Windows)
**示例**:
```csharp
// 定期释放内å˜
var timer = new TimerX(state =>
{
Runtime.FreeMemory();
}, null, 60_000, 60_000); // æ¯åˆ†é’Ÿæ‰§è¡Œä¸€æ¬¡
// 仅释放工作集,ä¸è§¦å‘GC
Runtime.FreeMemory(gc: false);
// 释放指定进程的内å˜
Runtime.FreeMemory(processId: 1234, gc: false);
```
> **注æ„**:频ç¹è°ƒç”¨ `FreeMemory` å¯èƒ½å½±å“性能,建议在内å˜åŽ‹åŠ›è¾ƒå¤§æ—¶å®šæœŸè°ƒç”¨ã€‚
## 使用场景
### 1. 跨平å°è·¯å¾„处ç†
```csharp
public String GetConfigPath()
{
if (Runtime.Windows)
return @"C:\ProgramData\MyApp\config.json";
else if (Runtime.Linux)
return "/etc/myapp/config.json";
else if (Runtime.OSX)
return "/Library/Application Support/MyApp/config.json";
else
return "config.json";
}
```
### 2. 容器环境适é…
```csharp
public void ConfigureServices()
{
if (Runtime.Container)
{
// 容器环境:从环境å˜é‡è¯»å–é…ç½®
var connStr = Runtime.GetEnvironmentVariable("DATABASE_URL");
services.AddDbContext<MyDbContext>(options =>
options.UseNpgsql(connStr));
}
else
{
// 本地开å‘:从é…置文件读å–
var connStr = Configuration.GetConnectionString("Default");
services.AddDbContext<MyDbContext>(options =>
options.UseNpgsql(connStr));
}
}
```
### 3. 内å˜ç›‘控与释放
```csharp
public class MemoryMonitor
{
private readonly Timer _timer;
private const Int64 MemoryThreshold = 500 * 1024 * 1024; // 500MB
public MemoryMonitor()
{
_timer = new Timer(CheckMemory, null, 0, 30_000);
}
private void CheckMemory(Object? state)
{
var gcMemory = GC.GetTotalMemory(false);
if (gcMemory > MemoryThreshold)
{
XTrace.WriteLine($"内å˜è¶…过阈值 ({gcMemory / 1024 / 1024}MB),开始释放");
Runtime.FreeMemory();
}
}
}
```
### 4. 性能计时器
```csharp
public class PerformanceTimer : IDisposable
{
private readonly String _operation;
private readonly Int64 _startTime;
public PerformanceTimer(String operation)
{
_operation = operation;
_startTime = Runtime.TickCount64;
}
public void Dispose()
{
var elapsed = Runtime.TickCount64 - _startTime;
XTrace.WriteLine($"{_operation} 耗时: {elapsed}ms");
}
}
// 使用
using (new PerformanceTimer("æ•°æ®åº“查询"))
{
var result = db.Query<User>().ToList();
}
```
## 最佳实践
### 1. å¹³å°ç‰¹å®šä»£ç 隔离
```csharp
// 推è:使用æ¡ä»¶åˆ¤æ–隔离平å°ç‰¹å®šä»£ç
public void DoWork()
{
if (Runtime.Windows)
DoWorkWindows();
else if (Runtime.Linux)
DoWorkLinux();
else
DoWorkDefault();
}
```
### 2. é¿å…频ç¹è°ƒç”¨ FreeMemory
```csharp
// 䏿ލèï¼šæ¯æ¬¡æ“作åŽéƒ½é‡Šæ”¾
foreach (var item in items)
{
ProcessItem(item);
Runtime.FreeMemory(); // æ€§èƒ½æ€æ‰‹ï¼
}
// 推è:批é‡å¤„ç†åŽé‡Šæ”¾ï¼Œæˆ–定时释放
foreach (var item in items)
{
ProcessItem(item);
}
Runtime.FreeMemory(); // 处ç†å®ŒæˆåŽç»Ÿä¸€é‡Šæ”¾
```
### 3. 使用 TickCount64 è€Œéž DateTime 计时
```csharp
// 䏿ލè:DateTime 计时å¯èƒ½å—系统时间调整影å“
var start = DateTime.Now;
DoWork();
var elapsed = (DateTime.Now - start).TotalMilliseconds;
// 推è:TickCount64 ä¸å—系统时间影å“
var start = Runtime.TickCount64;
DoWork();
var elapsed = Runtime.TickCount64 - start;
```
## 相关链接
- [æœºå™¨ä¿¡æ¯ MachineInfo](/NewLife/X/Blob/dev/Doc/machine_info-机器信æ¯MachineInfo.md)
- [日志系统 ILog](/NewLife/X/Blob/dev/Doc/log-日志ILog.md)
- [高级定时器 TimerX](/NewLife/X/Blob/dev/Doc/timerx-高级定时器TimerX.md)
|