当前位置: 首页 > news >正文

Gradio.Net 开发指南 -- 在 Blocks 中管理状态

目录

在 Blocks 中管理状态(State In Blocks)

全局状态(Global State)

会话状态(Session State)

无法深拷贝对象:按会话隔离实例

浏览器状态(Browser State)

总结


上一篇

Gradio.Net (https://github.com/feiyun0112/Gradio.Net)是一个开源的 .NET 库,它是 Gradio 的 .NET 移植版本,允许你为机器学习模型、API 或任何 C# 函数快速构建演示或 Web 应用程序,无需任何 JavaScript、CSS 或 Web 开发经验!

在 Blocks 中管理状态(State In Blocks)

当你使用gr.Blocks()构建应用时,通常会遇到“状态”问题:

  • 有些值需要在所有用户之间共享(例如访问计数);

  • 有些值只需要在单个用户会话内保留(例如购物车、聊天历史);

  • 有些值希望刷新页面后仍然保留(例如用户名、偏好设置)。

在 Gradio / Gradio.Net 中,常见有三种状态管理方式:

  • 全局状态(Global State):应用运行期间,所有用户共享。

  • 会话状态(Session State):仅对当前用户会话有效,刷新页面会重置。

  • 浏览器状态(Browser State):保存在浏览器 ‎localStorage,关闭/刷新后仍可恢复。

全局状态(Global State)

全局状态最简单:把变量定义在函数外部即可。下面示例里,visitorCount在所有用户之间共享。

using Gradio.Net; using Gradio.Net.Components; using Gradio.Net.Events; var visitorCount = 0; string IncrementCounter() { visitorCount += 1; return visitorCount.ToString(); } using var demo = gr.Blocks(); var number = gr.Textbox(label: "Total Visitors", value: "Counting..."); _ = gr.On( triggers: (List<EventListener>?)null, fn: IncrementCounter, outputs: number ); await demo.Launch();

代码

如果你不希望值在不同用户之间共享,请不要放在全局变量里,而应使用会话状态。

会话状态(Session State)

会话状态会在同一页面会话内持续保留,但不会跨用户共享;用户刷新页面后会重置。

使用步骤:

  1. 创建 ‎gr.State()(可传默认值)。

  2. 在事件监听里把该 ‎State作为输入和输出。

  3. 在函数参数和返回值中处理该状态。

下面是购物车示例:

using Gradio.Net; using Gradio.Net.Components; List<string> AddItems(List<string>? newItems, List<string>? previousCart) { var cart = new List<string>(previousCart ?? new()); if (newItems != null) { cart.AddRange(newItems); } return cart; } double CartSize(List<string>? cart) { return (cart ?? new List<string>()).Count; } using var demo = gr.Blocks(); var cart = gr.State(value: new List<string>()); var itemsToAdd = gr.CheckboxGroup(new[] { "Cereal", "Milk", "Orange Juice", "Water" }); var addButton = gr.Button("Add Items"); _ = addButton.Click( fn: AddItems, inputs: new object[] { itemsToAdd, cart }, outputs: cart ); var cartSize = gr.Number(label: "Cart Size"); _ = cart.Change( fn: CartSize, inputs: cart, outputs: cartSize ); await demo.Launch();

你可以把gr.State理解为一个“不可见组件”:前端不直接显示,但可以参与事件计算。

说明:gr.State的值需要可深拷贝(deepcopy-able)。如果状态对象本身无法深拷贝,请使用“按会话哈希维护全局字典”的方案。

无法深拷贝对象:按会话隔离实例

当对象(例如包含锁)无法深拷贝时,可以读取request.SessionHash,并在服务端用全局字典保存“每个用户会话”的实例。

using System.Collections.Concurrent; using Gradio.Net; using Gradio.Net.Components; using Gradio.Net.Core; using Gradio.Net.Events; var instances = new ConcurrentDictionary<string, NonDeepCopyable>(); string InitializeInstance(Request request) { if (string.IsNullOrWhiteSpace(request.SessionHash)) { return "Error: session hash missing"; } instances[request.SessionHash] = new NonDeepCopyable(); return "Session initialized!"; } double IncrementCounter(Request request) { if (string.IsNullOrWhiteSpace(request.SessionHash)) { return -1; } if (instances.TryGetValue(request.SessionHash, out var instance)) { return instance.Increment(); } return -1; } using var demo = gr.Blocks(); var output = gr.Textbox(label: "Status"); var counter = gr.Number(label: "Counter Value"); var incrementBtn = gr.Button("Increment Counter"); _ = gr.On( triggers: (List<EventListener>?)null, fn: InitializeInstance, outputs: output ); _ = incrementBtn.Click( fn: IncrementCounter, outputs: counter ); await demo.Launch(); class NonDeepCopyable { private readonly object _lockObj = new(); private int _counter; public int Increment() { lock (_lockObj) { _counter += 1; return _counter; } } }

浏览器状态(Browser State)

浏览器状态会写入本地localStorage,适合保存用户偏好、账号输入等信息。

using Gradio.Net; using Gradio.Net.Components; using Gradio.Net.Events; var random = new Random(); string GenerateToken(int len) { const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return new string(Enumerable.Range(0, len).Select(_ => chars[random.Next(chars.Length)]).ToArray()); } object[] GenerateRandomly() { var username = GenerateToken(10); var password = GenerateToken(10); return new object[] { username, password }; } object[] LoadFromLocalStorage(object? savedValues) { if (savedValues is System.Collections.IList list && list.Count >= 2) { return new object[] { list[0]?.ToString() ?? string.Empty, list[1]?.ToString() ?? string.Empty }; } return new object[] { string.Empty, string.Empty }; } object SaveToLocalStorage(string username, string password) { return new object[] { username, password }; } Markdown ShowSavedMessage() { var timestamp = DateTime.Now.ToString("hh:mm:ss tt"); return gr.Markdown($"✅ Saved to local storage at {timestamp}", visible: true); } using var demo = gr.Blocks(); _ = gr.Markdown("Your Username and Password will get saved in the browser's local storage. If you refresh the page, the values will be retained."); var username = gr.Textbox(label: "Username"); var password = gr.Textbox(label: "Password", type: "password"); var btn = gr.Button("Generate Randomly"); var localStorage = gr.BrowserState(defaultValue: new[] { "", "" }); var savedMessage = gr.Markdown("✅ Saved to local storage", visible: false); _ = btn.Click( fn: GenerateRandomly, outputs: new object[] { username, password } ); _ = gr.On( triggers: (List<EventListener>?)null, fn: LoadFromLocalStorage, inputs: localStorage, outputs: new object[] { username, password } ); _ = username.Change( fn: SaveToLocalStorage, inputs: new object[] { username, password }, outputs: localStorage ); _ = password.Change( fn: SaveToLocalStorage, inputs: new object[] { username, password }, outputs: localStorage ); _ = localStorage.Change( fn: ShowSavedMessage, outputs: savedMessage ); await demo.Launch();

注意:gr.BrowserState的值保存在浏览器中。若 Gradio 应用重启,默认随机storage_key/secret会变化,历史值可能无法继续读取。要跨重启读取,请固定storage_keysecret,并确保在可信应用场景中使用。

总结

这一章你学会了三种状态管理方式:

  • 全局状态:适合跨用户共享的运行期数据。

  • 会话状态:适合单用户会话内的临时数据。

  • 浏览器状态:适合需要在刷新后保留的前端数据。

引入地址

http://www.jsqmd.com/news/1325357/

相关文章:

  • 王慧文家族办公室AI投资布局:覆盖产业链多环节,折射行业早期探索状态
  • 从散装脚本到智能体操作系统:AgentOS架构设计与工程实践
  • 智识未来,眼见为实:2026武汉机器视觉展会开启感知技术新纪元
  • 2026年北京代理记账报税机构怎么选?资深财务顾问的6个判断维度 - 优质品牌商家
  • 润滑油价格哪个合理? - 中媒介
  • Unity开发核心:向量运算与坐标系转换实战指南
  • R语言mice包处理数据缺失值的原理与实践
  • 汽车零部件降尘试验箱 整车电子沙尘可靠性测试
  • 2026年全国公寓组合床厂家推荐选购相关知识科普 - 李lixpi
  • 从BI到AI:企业数据底座的演进与重构
  • Kimi K3 开放权重后,我更确定:AI 编程的瓶颈已经不是模型
  • 全国售后服务响应快的包灌装设备服务商哪家? - 中媒介
  • Windows安卓子系统(WSA)开发指南:让安卓应用在Windows 11上完美运行
  • 2024下半年必装的AI搜索工具清单:仅剩最后47个免费API额度,速领技术人专属通道
  • 2026 年更新:蒸湘口碑好的厂房外墙彩绘服务商有哪些,别让闲置厂房外墙烂成“牛皮癣”,这波操作竟能年省十万宣传费?-唐宫墙体彩绘雕塑 - 实业推荐官
  • MATLAB MAB 5.0建模规范详解与工程实践
  • PyTorch 2.0核心升级与性能优化实战指南
  • 源-荷-储系统优化:雨流计数法与双层协同框架实践
  • DeepSeek-V4-Flash正式版来袭,真的掀桌了!完成一篇完整的学术文章只要……
  • Flutter三方库鸿蒙适配实战:以annas_archive_api为例
  • Java开发者如何应对技术焦虑:从稳固基本盘到AI Agent开发的演进路径
  • MMD Tools:Blender中MMD格式转换的终极解决方案
  • 2026年不锈钢气体接头公司避坑指南:这五家为什么被大厂偏爱 - 品牌报告
  • 4G低功耗土壤温湿度采集器:数据多人共享,团队协同监管更高效
  • 实战:用 Python 自动化检测 YUM/DNF 仓库中上万 RPM 包的文件冲突
  • Ubuntu VNC远程桌面配置:从服务端部署到SSH安全隧道实战
  • 塞尔维亚的海外劳动力外包是什么?
  • 终极免费手机号码定位工具:快速查询电话号码归属地并在地图上精确定位
  • 瑞德克斯平台:把客户支持做到位——清单盘点与提示整理
  • 零基础FastAPI急速入门教程|3分钟搭建最小可运行项目(含接口文档+启动调试)