# Rx.NET 响应式编程演示 **Repository Path**: unbengable/RxNet ## Basic Information - **Project Name**: Rx.NET 响应式编程演示 - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-20 - **Last Updated**: 2026-04-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: Csharp, 响应式编程 ## README # Rx.NET 响应式编程演示 一个交互式的 WPF 应用程序,展示 Rx.NET (Reactive Extensions) 的核心概念和常用操作符。通过6个生动的演示,让你直观感受响应式编程的魅力。 ![RxDemo界面](Home.jpg) ## 📋 项目结构 ``` RxDemo/ ├── RxDemo.csproj # 项目文件,引用 Rx.NET 和 Prism ├── App.xaml/.cs # 应用入口 ├── Views/ │ ├── MainWindow.xaml # 主窗口 │ ├── RxDemoView.xaml # 演示界面(6个演示模块) │ └── RxDemoView.xaml.cs # 后端代码(事件转发) └── ViewModels/ ├── RxDemoViewModel.cs # 演示逻辑(Rx流定义) └── MainWindowViewModel.cs # 主窗口逻辑 ``` ## 🚀 快速开始 ### 环境要求 - .NET 6.0 SDK 或更高版本 - Windows 操作系统(WPF应用) - Visual Studio 2022 或 VS Code + C# 扩展 ### 运行步骤 ```bash # 克隆/下载项目后,进入项目目录 cd RxDemo # 还原 NuGet 包 dotnet restore # 编译项目 dotnet build # 运行应用程序 dotnet run --project RxDemo/RxDemo.csproj ``` ## 📚 六大演示详解 ### 1. 🔍 实时搜索防抖 (Throttle) **功能**:在搜索框输入文字,系统会在你停止输入 **500毫秒** 后才执行搜索。 **涉及操作符**: - `FromEventPattern` - 将 .NET 事件转换为 Observable - `Throttle` - 防抖,等待一段时间无新值后才发射最后一个值 - `SelectMany` - 将搜索逻辑映射到 Observable **实际应用场景**:搜索框实时提示、表单验证 ```csharp Observable.FromEventPattern(...) .Throttle(TimeSpan.FromMilliseconds(500)) // 防抖500ms .SelectMany(text => SearchAsync(text)) // 异步搜索 .Subscribe(result => ShowResult(result)); ``` --- ### 2. 👆 点击流缓冲处理 (Buffer) **功能**:在2秒内快速点击按钮,系统会收集所有点击并批量统计处理。 **涉及操作符**: - `Subject` - 既是 Observable 又是 Observer,连接命令式代码和响应式代码 - `Buffer(TimeSpan)` - 时间窗口缓冲,收集一段时间内的所有事件 **实际应用场景**:批量处理、日志收集、网络请求合并 ```csharp clickSubject .Buffer(TimeSpan.FromSeconds(2)) // 2秒时间窗口 .Where(batch => batch.Count > 0) // 过滤空批次 .Subscribe(batch => ProcessBatch(batch)); ``` --- ### 3. 📊 实时数据流 (Interval/TakeWhile) **功能**:点击"开始"按钮,系统每200毫秒生成模拟传感器数据(温度、湿度)。 **涉及操作符**: - `Interval` - 定时发射递增序列 - `TakeWhile` - 条件持续订阅,满足条件时继续,否则停止 - `ObserveOn` - 指定观察者在UI线程执行 **实际应用场景**:实时监控、数据仪表盘、心跳检测 ```csharp Observable.Interval(TimeSpan.FromMilliseconds(200)) .TakeWhile(_ => !cancellationToken.IsCancellationRequested) .Select(i => GenerateSensorData(i)) .ObserveOn(SynchronizationContext.Current) .Subscribe(data => UpdateUI(data)); ``` --- ### 4. ✋ 鼠标拖拽事件流 (SelectMany/TakeUntil) **功能**:在白色区域内拖拽橙色圆形,展示如何组合鼠标事件实现拖拽。 **涉及操作符**: - `SelectMany` - 将每个 MouseDown 映射为 MouseMove 流 - `TakeUntil` - 直到 MouseUp 发生时停止流 - `Finally` - 流完成时清理状态 **实际应用场景**:拖拽排序、画图应用、自定义控件 ```csharp mouseDownSubject .SelectMany(down => { var startPos = GetPosition(); return mouseMoveSubject .TakeUntil(mouseUpSubject) // 直到鼠标抬起 .Select(move => CalculateNewPosition(move, startPos)); }) .Subscribe(pos => UpdatePosition(pos)); ``` --- ### 5. ⌨️ 键盘组合键检测 (键盘事件流) **功能**:点击键盘捕获区域后按键盘,检测 Ctrl+C、Ctrl+V 等组合键。 **涉及操作符**: - `Subject` - 转发键盘事件 - 使用 `KeyboardDevice.Modifiers` 检测修饰键状态 **实际应用场景**:快捷键系统、游戏控制、效率工具 ```csharp keyDownSubject .Subscribe(e => { bool isCtrl = (e.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0; if (e.Key == Key.C && isCtrl) Show("Ctrl+C 复制"); }); ``` --- ### 6. ⚡ 异步操作链 (Concat/Catch) **功能**:点击按钮启动异步链:验证 → 获取数据 → 处理保存。 **涉及操作符**: - `Concat` - 顺序执行多个 Observable,一个完成后再执行下一个 - `Catch` - 错误处理,捕获异常并返回替代值 - `ObserveOn` - 确保回调在UI线程执行 **实际应用场景**:流程审批、数据同步、事务处理 ```csharp Observable.Concat(step1, step2, step3) .Catch(ex => Observable.Return($"错误: {ex.Message}")) .Subscribe( message => UpdateStatus(message), () => ShowComplete() ); ``` ## 🧩 响应式编程核心概念 ### 1. Observable (可观察对象) 表示一个异步数据流,可以发射零个或多个值,然后完成或出错。 ### 2. Observer (观察者) 订阅 Observable,响应三个事件: - `OnNext(T)` - 接收到新值 - `OnError(Exception)` - 发生错误 - `OnCompleted()` - 流完成 ### 3. 操作符 (Operators) 用于转换、过滤、组合数据流: - **创建**:`Create`, `Interval`, `FromEventPattern`, `Subject` - **转换**:`Select`, `SelectMany`, `Buffer` - **过滤**:`Where`, `Take`, `TakeUntil`, `TakeWhile`, `Throttle` - **组合**:`Concat`, `Merge`, `Zip`, `CombineLatest` - **调度**:`ObserveOn`, `SubscribeOn` ### 4. 调度器 (Schedulers) 控制代码执行的线程: - `SynchronizationContext.Current` - UI线程 - `Scheduler.Default` - 线程池 - `Scheduler.Immediate` - 立即执行 ## 📝 代码注释说明 项目中的代码包含大量中文注释,详细解释: - 每个 Rx 操作符的作用 - 数据流的转换过程 - 线程切换的原因 - 内存管理(Disposable) 建议从 `RxDemoViewModel.cs` 开始阅读,这是整个演示的核心逻辑所在。 ## 🔧 关键实现技巧 ### 防止内存泄漏 ```csharp private readonly CompositeDisposable _disposables = new(); // 订阅时添加到集合 disposables.Add(stream); // 清理时统一释放 public void Dispose() => _disposables.Dispose(); ``` ### 命令式代码与响应式代码的连接 ```csharp // Subject 作为桥梁 private readonly Subject _clickSubject = new(); // WPF 事件调用 private void OnButtonClick() => _clickSubject.OnNext(Unit.Default); // Rx 流订阅 _clickSubject.Buffer(TimeSpan.FromSeconds(2)).Subscribe(...); ``` ### UI线程更新 ```csharp stream .ObserveOn(SynchronizationContext.Current) // 切换到UI线程 .Subscribe(data => UpdateUI(data)); // 安全更新界面 ``` ## 📖 学习建议 1. **按顺序体验6个演示**,每个演示都有明确的学习目标 2. **对照代码和界面**,理解操作符如何影响数据流 3. **修改参数尝试**:如修改 Throttle 的时间、Buffer 的窗口大小 4. **阅读 ViewModel 中的注释**,了解每个操作符的实际意义 ## 🔗 相关资源 - [Rx.NET 官方文档](https://github.com/dotnet/reactive) - [ReactiveX 操作符图解](http://reactivex.io/documentation/operators.html) - [响应式编程介绍](https://reactivex.io/intro.html) ## 🐛 已知问题 - 项目使用 .NET 6,编译时会有过时版本警告(不影响运行) - 演示3的数据流在停止后需要重新点击开始才能再次启动 ## 📄 许可证 MIT License - 自由使用和学习 --- **Happy Coding with Rx!** 🎉