同一机器中,Blazor WASM与Windows Worker Service如何实现数据共享存储?
同一机器下Blazor WASM与Windows Worker Service的数据共享方案
以下是几种适配你需求的实用实现方式,核心是绕过浏览器沙箱限制,建立双方可访问的共享存储或通信通道:
方案1:本地共享目录 + File System Access API(浏览器端)+ 文件监控(Worker Service)
这种方式依赖现代浏览器的文件系统访问能力,让用户指定共享目录,Worker Service监控该目录的文件变化来读取GUID。
Blazor WASM端实现步骤
- 引入JS互操作代码,调用浏览器API选择目录并写入文件:
// wwwroot/js/file-utils.js async function writeGuidToFile(guid, directoryHandle) { const fileHandle = await directoryHandle.getFileHandle('guid-store.txt', { create: true }); const writable = await fileHandle.createWritable(); await writable.write(guid); await writable.close(); return true; } async function selectDirectory() { return await window.showDirectoryPicker(); }
- 在Blazor组件中调用JS方法写入GUID:
// Pages/Index.razor @inject IJSRuntime JS <button @onclick="WriteGuid">写入GUID到共享目录</button> @code { private async Task WriteGuid() { var directoryHandle = await JS.InvokeAsync<IJSObjectReference>("selectDirectory"); var newGuid = Guid.NewGuid().ToString(); await JS.InvokeAsync<bool>("writeGuidToFile", newGuid, directoryHandle); } }
Windows Worker Service端实现步骤
使用FileSystemWatcher监控指定目录,读取文件内容:
// Worker.cs protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var watcher = new FileSystemWatcher(@"C:\SharedGuidDirectory") { Filter = "guid-store.txt", NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName }; watcher.Changed += OnFileChanged; watcher.Created += OnFileChanged; watcher.EnableRaisingEvents = true; while (!stoppingToken.IsCancellationRequested) { await Task.Delay(1000, stoppingToken); } } private void OnFileChanged(object sender, FileSystemEventArgs e) { try { var guid = File.ReadAllText(e.FullPath); Console.WriteLine($"读取到新的GUID: {guid}"); } catch (IOException) { Task.Delay(500).ContinueWith(_ => OnFileChanged(sender, e)); } }
注意事项
- 仅支持Chrome、Edge、Firefox 118+等现代浏览器
- 需要用户手动选择共享目录,无法静默写入本地文件
方案2:Worker Service内置本地HTTP服务(推荐)
Worker Service启动轻量级HTTP服务器,暴露API接口让Blazor WASM发送GUID,Worker Service存储并读取该数据。这种方式无需用户操作,兼容性更好。
Windows Worker Service端实现步骤
- 添加NuGet包:
Microsoft.AspNetCore.App - 配置并启动Kestrel服务器:
// Program.cs using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddHostedService<Worker>(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseUrls("http://localhost:5000"); webBuilder.Configure(app => { app.MapPost("/api/guid", async context => { var guid = await context.Request.ReadFromJsonAsync<string>(); File.WriteAllText(@"C:\WorkerData\latest-guid.txt", guid); await context.Response.WriteAsync("GUID已存储"); }); app.MapGet("/api/guid", async context => { if (File.Exists(@"C:\WorkerData\latest-guid.txt")) { var guid = File.ReadAllText(@"C:\WorkerData\latest-guid.txt"); await context.Response.WriteAsync(guid); } else { context.Response.StatusCode = StatusCodes.Status404NotFound; } }); }); }) .Build(); await host.RunAsync();
- Worker Service中读取存储的GUID:
// Worker.cs protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { if (File.Exists(@"C:\WorkerData\latest-guid.txt")) { var guid = File.ReadAllText(@"C:\WorkerData\latest-guid.txt"); Console.WriteLine($"当前存储的GUID: {guid}"); } await Task.Delay(5000, stoppingToken); } }
Blazor WASM端实现步骤
通过HTTP请求发送GUID到本地API:
// Pages/Index.razor @inject HttpClient Http <button @onclick="SendGuid">发送GUID到Worker Service</button> @code { private async Task SendGuid() { var newGuid = Guid.NewGuid().ToString(); await Http.PostAsJsonAsync("http://localhost:5000/api/guid", newGuid); var storedGuid = await Http.GetStringAsync("http://localhost:5000/api/guid"); Console.WriteLine(storedGuid); } }
注意事项
- 确保Worker Service以管理员权限运行(如果写入系统目录)
- 可将存储方式替换为SQLite、本地DB等更可靠的存储方案
方案3:本地SQLite数据库
使用SQLite文件作为共享存储,Blazor WASM通过File System Access API打开SQLite文件并写入数据,Worker Service直接读取该文件。
Blazor WASM端实现
引入SQLite的WASM库(如SQLite-net-pcl),结合File System Access API操作本地SQLite文件:
// 示例代码(需引入SQLite相关包) private async Task WriteGuidToSqlite() { var directoryHandle = await JS.InvokeAsync<IJSObjectReference>("selectDirectory"); var fileHandle = await directoryHandle.GetFileHandle("guid-db.sqlite", new { create = true }); var db = new SQLiteAsyncConnection(fileHandle); await db.CreateTableAsync<GuidRecord>(); await db.InsertAsync(new GuidRecord { Value = Guid.NewGuid().ToString() }); } public class GuidRecord { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string Value { get; set; } }
Worker Service端实现
使用Microsoft.Data.Sqlite读取SQLite文件:
private async Task ReadGuidFromSqlite() { using var connection = new SqliteConnection("Data Source=C:\\SharedData\\guid-db.sqlite"); await connection.OpenAsync(); var command = connection.CreateCommand(); command.CommandText = "SELECT Value FROM GuidRecord ORDER BY Id DESC LIMIT 1"; var latestGuid = await command.ExecuteScalarAsync() as string; Console.WriteLine(latestGuid); }
注意事项
- Blazor WASM端需处理SQLite WASM的兼容性问题
- 需确保双方操作数据库时的锁机制,避免读写冲突
内容的提问来源于stack exchange,提问作者Ali.Rashidi
相关产品推荐
相关产品推荐

