Windows Forms 中运行 Web 服务器
当大伙伴们看到标题后是不是在怀疑老周在灌水非也老周向来只会造水从来不灌水。哪怕写的主题和别人一样但水的内容也肯定与他人不同。这是老周特色熟悉老周的大伙伴都知道的。哦顺便提一下有人投诉老周写的东西没用根本不能在项目中使用。项目中用什么怎么用是你的项目经验和实力问题老周可不负这个责。老周只传递知识和一些可能对你有用的技巧如果你想着坐享其成生吞他人劳动成果的话请到别处去。也有人说老周写的代码太“不正经”了老周问你什么样的代码才算“正经”你不用管老周写的什么代码你看懂了学到一点点知识就行了这个才是最重要的。老周瞎编的代码一方面是防搜索引擎另一方面是防 AI 侵权。现在想不劳而获的人太多了不防不行。请记住任何措施仅限于防小人而非防君子。好说回正题如何把 APS.net core 框在 Windows Forms 或 WPF 中网上资料很多了老周你还扯啥。不老周还真要扯一下的。最近老周接了一个很“简单”的项目就是车间大约有 45 台压条机姑且这么叫吧也不知道机器的真名叫什么反正工人是这么叫的。它的作用是把铁皮压直了一根根像躺尸似的直挺挺的对就是把那一条条的不知名金属弄直了。现在老板太想进步了请人改造了机器加了一块 ESP32 C3 模组机器每拉直一条不知名金属就会通过 Wifi 上报结果HTTP POST。他们请另外的团队做了固件但问题它能上传了没人接收。所以老周的工作就是搞一个 HTTP 服务器公开 Web API 让 Esp32 调用接收到数据后把结果保存到数据库。然后车间的大屏幕上要实时展示就像股票交易所大厅那样。由于工厂里面的人可能不会搞那么复杂的配置最好就是搞个 exe他们双击运行就完事了。于是自然要把 ASP.NET Core 弄到 WinForms 程序里。为了省事基础代码打算让打工皇帝 AI 去干结果它给的代码是寒武纪时期的。然后网上搜搜也确实很多代码都是寒武纪时期的。现代版的只有微软自己文档有提到。今天老周干脆分享一下让新手伙伴们不迷路。接下来老周用最简单的方式讲讲理论部分。第一先认准哪些 API 是你要的。ASP.NET Core 其实是用 .NET 的 Host 来启动的所以先记住 Microsoft.Extensions.Hosting 这个包。第二在同名的命名空间下你会看到这样的让人迷惑的场景。image那么多 Builder我用哪个一句话斯基凡看到 HostBuilder 就忽略那是寒武纪时代的遗物现代版要认准 HostApplicationBuilder 类基础接口 IHostApplicationBuilder。先别急接下来老周给看看这些玩意儿是怎么玩的。现在各位不想 ASP.NET Core 的事暂时把它忘了。刚刚我们认识了一个类叫 HostApplicationBuilder它的构造函数复制代码// 无参版本public HostApplicationBuilder();// 需要命令行参数版本public HostApplicationBuilder(string[]? args);// 源头版本public HostApplicationBuilder(HostApplicationBuilderSettings? settings);复制代码说到底就是需要一个 HostApplicationBuilderSettings 对象它的作用是配置应用程序的基本信息。其中ApplicationName 和 Args 属性用得最多。HostApplicationBuilder(string[] args) 构造函数就是设置了 Args 属性。public HostApplicationBuilder(string[]? args)this(new HostApplicationBuilderSettings { Args args }){}于是动手能力强的你就会……复制代码// 记得添加 Microsoft.Extensions.Hosting 包的引用static void Main(string[] args){HostApplicationBuilder appBuilder new(args);var myHost appBuilder.Build(); myHost.Run();}复制代码这个逻辑对吗那就得运行下如果能看到如下输出说明是对的。image这个能干啥答啥也不能干。有.NET 基础的大伙伴一定想到得加几个东西到服务容器里才行。复制代码public class MyService{public void Boom(){Console.WriteLine(“*** 自爆程序已启动 ***”);}}static void Main(string[] args){HostApplicationBuilder appBuilder new(args);appBuilder.Services.AddTransient();var myHost appBuilder.Build(); myHost.Run();}复制代码运行之后咦没反应。那当然了服务你是加了可谁调用不管你添加的服务有多少个它们之间什么依赖关系。但万事总有个头啊起码有一个要先被调用吧。那么……复制代码static void Main(string[] args){HostApplicationBuilder appBuilder new(args);appBuilder.Services.AddTransient();var myHost appBuilder.Build(); IHostApplicationLifetime lifeTime myHost.Services.GetRequiredServiceIHostApplicationLifetime(); lifeTime.ApplicationStarted.Register(() { Console.WriteLine( 应用程序启动 ); MyService svc myHost.Services.GetRequiredServiceMyService(); svc.Boom(); }); lifeTime.ApplicationStopping.Register(() { Console.WriteLine( 应用程序即将停止 ); }); myHost.Run();}复制代码是个大聪明获取 IHostApplicationLifetime 服务毕竟这个服务是框架自动添加的当 Host 启动后会触发 ApplicationStarted而 ApplicationStopping 是在 Host 即将完蛋时触发而且它会一直 block直到注册的委托执行完成。所以ApplicationStopping 注册的委托中你的代码不要执行太久否则会耽误应用程序去投胎的时间。ApplicationStarted、ApplicationStopping、ApplicationStopped 虽然定义的是属性成员其实和事件一样。虽然它是 CancellationToken 类型但这个结构体可以用 Register 方法注册一个委托当发生取消时调用这个委托。你看看这不跟事件一个德性吗。所以咱们上面的代码就是在应用启动后调用 MyService 服务那不就可以运行了吗。image现在应用程序阻止了主线程直到程序结束。怎么结束日志上不是写了吗按 Ctrl C。image这样做虽然能调用服务但一来不好控制二来万一你那个服务不行一执行就挂了或者在那里死循环就会让后面的程序无法执行了。所以这个方案还是不佳。于是有一个神秘的服务浮出水面—— IHostedService。这个服务接口只有两个方法。A、StartAsyncB、StopAsync。看名字就知道开始和结束呗。咱们实现一下。复制代码public class MyHostedService : IHostedService{MyService src;public MyHostedService(MyService s) src s; public Task StartAsync(CancellationToken cancellationToken) { Console.WriteLine( 服务已启动 ); src.Boom(); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { Console.WriteLine( 服务停止 ); return Task.CompletedTask; }}复制代码MyService 服务只要通过构造函数参数就能获得这就是依赖注入。现在我们不需要 IHostApplicationLifetime 服务了直接把 MyHostedService 放进服务容器就行了。复制代码static void Main(string[] args){HostApplicationBuilder appBuilder new(args);appBuilder.Services.AddTransient();appBuilder.Services.AddSingletonIHostedService, MyHostedService();var myHost appBuilder.Build(); myHost.Run();}复制代码hosted 的服务最好生命周期为单实例毕竟它不需要多次实例化很多时候它的生命周期贯穿整应用程序。代码运行结果如下image实现了 IHostedService 接口的服务到底神在哪神就神在框架会自动调用它。因为这种服务实现的接口必然是 IHostedService为了方便大家调用.NET 还提供了 AddHostedService 方法。这个方法添加以 IHostedService 为基础接口的服务类型且注册为单实例。和我们上面的写法功能一样只是方便。复制代码static void Main(string[] args){HostApplicationBuilder appBuilder new(args);appBuilder.Services.AddTransient();appBuilder.Services.AddHostedService();var myHost appBuilder.Build(); myHost.Run();}复制代码现在你应该知道ASP.NET Core 的内置服务器能自动运行的原因了吧就是实现了 IHostedService 接口。如果咱们继续深挖会发生什么呢在 VS 中打开项目属性窗口按下面所示修改属性。imageimage项目文件会变成这样。复制代码WinExe net10.0-windows enable enable True 复制代码 是不是很熟悉这不就是 WinForms 项目吗。复制代码public class MyMainForm : Form{private Label someText;public MyMainForm(){this.SuspendLayout(); // 控件多的时候可以减少闪烁Text “主窗口”;Size new Size(600, 480);someText new Label(){Text “这是一个简单得要死的程序”,Font new Font(“微软雅黑”, 12.0f),AutoSize true};someText.Location new Point(35, 40);this.Controls.Add(someText);ResumeLayout(); // 控件初始化完成统一刷新}}[STAThread]static async Task Main(string[] args){HostApplicationBuilder appBuilder new(args);var myHost appBuilder.Build(); await myHost.StartAsync(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // 系统 DPI 缩放优先 Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.Run(new MyMainForm()); // 主窗口关闭后终止 Host await myHost.StopAsync();}复制代码1、Main 方法上记得加上 [STAThread]2、由于 Application.Run 会在主窗口上进行消息循环处理它会阻塞当前线程。所以要先启动 Application Host再运行 Run 方法。等 Run 方法退出后再 Stop Host。3、其他窗口可以放服务容器中让它们也可以依赖注入。不过主窗口如果需要处理消息循环还是不要放容器中。好了折腾到这里相信换成 ASP.NET Core你也知道怎么弄了。我们新建一个 ASP.NET Core 项目什么类型都可以MVC、Blazor 或 空白 都行。然后打开项目属性窗口。这回知道怎么配置了吧和前文说的一样。

相关新闻

C++ vector迭代器失效原理与安全操作实践指南

C++ vector迭代器失效原理与安全操作实践指南

1. 项目概述&#xff1a;从一次诡异的崩溃说起那天下午&#xff0c;我正在调试一个处理日志数据的模块&#xff0c;代码逻辑很简单&#xff1a;遍历一个std::vector<std::string>&#xff0c;根据某些规则删除不符合条件的日志条目。我写了一个经典的for循环&#xff0c;…

2026/7/22 9:03:29阅读更多 →
PCIe高速接口技术解析与工程实践

PCIe高速接口技术解析与工程实践

1. PCIe高速接口的技术演进与核心优势 PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;作为现代计算机系统中最重要的高速串行总线标准&#xff0c;已经彻底取代了传统的PCI和AGP接口。从2003年PCIe 1.0标准发布至今&#xff0c;其带宽性能几乎每三年翻…

2026/7/22 9:03:29阅读更多 →
OpenCV 5发布:DNN引擎重构,AI模型推理性能提升42%

OpenCV 5发布:DNN引擎重构,AI模型推理性能提升42%

OpenCV 5 正式发布了&#xff0c;这是自2018年OpenCV 4发布以来最大的一次更新。这次更新重点重构了DNN引擎&#xff0c;原生支持大模型推理&#xff0c;在AI模型部署性能上有了显著提升。对于从事计算机视觉、AI模型部署的开发者来说&#xff0c;这是一个值得关注的重要版本。…

2026/7/22 9:03:29阅读更多 →
50元打造4K影音中心:CM311-1A刷机CoreELEC全攻略

50元打造4K影音中心:CM311-1A刷机CoreELEC全攻略

1. 项目概述&#xff1a;低成本打造家庭影音中心的替代方案 斐讯N1曾经是性价比极高的电视盒子改装神器&#xff0c;但随着市场存量减少和价格上涨&#xff0c;50元价位的CM311-1A正在成为新的性价比之王。这款中国移动魔百和定制机顶盒采用Amlogic S905L3芯片方案&#xff0c;…

2026/7/22 10:13:39阅读更多 →
【前端分享】vue开发项目,如何实现 从A页面跳转到B页面,并传值!

【前端分享】vue开发项目,如何实现 从A页面跳转到B页面,并传值!

Vue 页面双向跳转传值&#xff08;A↔B&#xff09;完整实现在 Vue 中实现 A → B → A 并携带参数回传&#xff0c;核心用 Vue Router 配合路由传参&#xff0c;最常用两种方案&#xff1a;编程式导航 query/params 传参&#xff08;简单场景&#xff09;、路由守卫 状态管理…

2026/7/22 10:13:39阅读更多 →
计算机毕业设计之在线旅行观光服务平台

计算机毕业设计之在线旅行观光服务平台

随着计算机技术&#xff0c;网络技术的迅猛发展&#xff0c;Internet 的不断普及&#xff0c;网络在各个领域里发挥了越来越重要的作用。特别是随着近年人民生活水平不断提高&#xff0c;在线旅行观光服务给旅行社的业务带来了更大的发展机遇。在经济快速发展的带动下&#xff…

2026/7/22 10:13:39阅读更多 →
序列之元组

序列之元组

元组Tuple 元组是一个不可变的、有序的元素集合。 不能对元组中的元素进行修改操作。 元组使用 () 定义&#xff0c;数据之间使用,分隔。 元组中每个元素都有对应的位置值&#xff0c;称为索引或下标&#xff0c;索引从起始从0开始向后逐个递增&#xff0c;并且从末尾从…

2026/7/22 10:13:39阅读更多 →
计算机毕业设计之在线课堂问答教学系统设计与实现

计算机毕业设计之在线课堂问答教学系统设计与实现

在线课堂问答教学是由高校学生依据兴趣爱好自愿组成&#xff0c;按照章程自主开展在线课堂问答教学。在线课堂问答教学是实施素质教育的重要途径和有效方式&#xff0c;在加强校园文化建设、提高学生综合素质、引导学生适应社会、促进学生成才就业等方面发挥着重要作用&#xf…

2026/7/22 10:13:39阅读更多 →
(81页PPT)中小学智慧校园建设方案(附下载方式)

(81页PPT)中小学智慧校园建设方案(附下载方式)

篇幅所限&#xff0c;本文只提供部分资料内容&#xff0c;完整资料请看下面链接 https://download.csdn.net/download/2501_92808811/92962768 资料解读&#xff1a;中小学智慧校园建设方案 详细资料请看本解读文章的最后内容。本方案立足国家教育信息化发展战略&#xff0c;…

2026/7/22 10:11:39阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序&#xff0c;最常见的矛盾是预算有限&#xff0c;但又不希望功能太单薄&#xff1b;没有技术团队&#xff0c;但又希望后续能自己运营&#xff1b;想快速上线&#xff0c;又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”&#xff0c;很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销&#xff0c;最怕钱花完了&#xff0c;资产没有留下。 效果广告能带来一段时间的曝光&#xff0c;但预算停止后&#xff0c;流量往往也随之停止。短视频内容可能在几天内冲高&#xff0c;也可能很快沉下去。AI搜索时代&#xff0c;企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定&#xff1a;何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮&#xff0c;用户已经关窗口了 Agent 与人最大的区别是&#xff1a;人知道什么时候该停下来给答案&#xff0c;Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →