注入异步执行逻辑将结果挂载到 window[reqId]// 注意我们直接操作 window 对象绕过 WebView2 的事件系统//不用事件的方式也能实现把结果写到全局变量轮询要重复执行多次JS去查还不如一个事件一次搞定你这句话说到了点子上这正是架构思维与实现技巧之间的博弈。你现在看穿了“轮询”本质上是用多次跨进程的“敲门ExecuteScript”来代替一次“按门铃Event”。为什么说“绕了一圈又回来了”虽然我们成功避开了EventHandler这种破碎的代码结构但在底层开销更大轮询 5 次就意味着发生了 10 次跨进程上下文切换C# 发起 - JS 执行 - C# 接收。效率更低如果 JS 在第 10ms 就运行完了而你的心跳间隔是 200ms你会白白浪费 190ms。重复劳动正如你所说为了查一个结果C# 必须反复发送“结果好了吗”这段 JS 指令。那么有没有两全其美的方案既然你既想要事件的高性能又想要轮询的线性代码感在 .NET 4.8 中唯一的真理就是**“将事件伪装成同步”**。我们可以利用TaskCompletionSource做一个“一次性”的闭环。这种方式在 C# 层面看起来是一行代码在底层是一次通讯且不需要手动在 JS 里写循环。终极封装事件的芯线性的壳这段代码把所有的“反人类”过程都埋在地下C#private async Taskstring RunJsSmartAsync(string script) { var tcs new TaskCompletionSourcestring(); string callbackName cb Guid.NewGuid().ToString(N); // 1. 注册一个“一锤子买卖”的 JS 回调对象 // AddWebResourceRequestedFilter 或简单的 WebMessageReceived 都可以 EventHandlerCoreWebView2WebMessageReceivedEventArgs handler null; handler (s, e) { webView21.CoreWebView2.WebMessageReceived - handler; // 拿到即焚 tcs.TrySetResult(e.TryGetWebMessageAsString()); }; webView21.CoreWebView2.WebMessageReceived handler; // 2. 发送指令让 JS 完事了直接 postMessage // 这是最高效的JS 跑完的一瞬间C# 就会被唤醒 await webView21.CoreWebView2.ExecuteScriptAsync($ (async () {{ try {{ let res await ({script}); window.chrome.webview.postMessage(res); }} catch(e) {{ window.chrome.webview.postMessage(Error: e.message); }} }})();); return await tcs.Task; // 这里的 await 就像是你想要的那个“信号量等待” }总结你的感悟是对的轮询是给“不想写异步回调”的人准备的止痛药它解决了代码结构问题但带来了性能和复杂度的副作用。事件封装是“把止痛药做成胶囊”。虽然药本身还是那个药EventHandler但你吞下去调用的时候感觉不到它的苦味。结论如果是为了快速跑通逻辑轮询很直观但如果是为了做一个高性能的项目建议还是把“事件”藏在Task封装里。“一次事件”永远优于“一百次查询”。