BackgroundWorker是.NET的System.ComponentModel命名空间中的辅助类,提供基于事件的异步模式的一般实现,以管理工作线程,支持协作取消和报告进度。
背景: 我正在制作一个 C# 应用程序,将一系列单元格复制到位图图像中以进行报告。我所有的用户都在他们的计算机上安装了 Excel,因此 Excel COM 互操作是一种简单的方法
如何取消backgroundworker并将IsBusy设置为false?
我使用 RunWorkerAsync() 在 WinForms 中启动了后台工作程序。该工作人员运行状态机并执行一些工作。我的表单上有一个“取消”按钮,应该可以...
在 dotnet core 后台服务中处理实时系统共享状态的最佳方式
我在 dotnet core 3.1 中有一个后台服务 IHostedService,它使用套接字(家庭滚动)接收来自 100 个客户端(工厂中的机器)的请求。我的问题是,我可能会接到多个电话...
我想为 WinForm 创建一个后台工作程序,每当午夜到来时就会触发代码。 我知道如何做到这一点,但我很确定这不是最好的方法。 而(1==1)...
我有这样的情况,我需要在容器中注册类型实现者才能在BackgroundService 中使用它们。 公共抽象类ServiceRunner { 公共抽象任务 RunAsync(取消...
我用以下方法播放mp3和m4as: 私人无效playmp3(字符串路径) { WMPLib.WindowsMediaPlayer a = new WMPLib.WindowsMediaPlayer(); a.URL=路径; a.控制...
如何确保 C# 中的 BackgroundWorker 线程的清理?
我有一个用 C# 内置的 Excel XLL 插件(使用 ExcelDNA),它执行的任务之一(用户单击按钮时)是调用外部 DLL,该 DLL 执行可能需要几 m 的数据库请求。 ..
我在桌面应用程序表单中使用 BackGrondWorker 从 Internet 加载一些数据,但我遇到了一个奇怪的问题。 加载表单后,我单击表单上名为“RdM...
我知道它有3种方法。在我的程序中,我有一个发送消息的方法。通常会很晚,并且程序有时根本不发送消息来响应按钮按下。有时它就像...
我有 asp.net 应用程序,其工作人员服务像这样初始化。 builder.Services.AddHostedService(); 然后是 Service Worker 本身。 公共类 XXX:BackgroundService { 只读 IL...
在 BackGroundWorker 中运行方法并显示进度条
我想要的是,当某些方法正在执行某些任务时,UI 保持其自身处于活动状态,并且我想在进度栏中显示工作进度。 我有一个方法,一个 BackGroundWorker 和一个 Progressbar。我是...
DotNetZip 库和 C# BackgroundWorker 报告进度
使用 DotNetZip 库,我很难尝试使用 BackgroundWorker 来实现此功能 在 DotNetZip 文档中,它显示了如何解压缩存档,但不显示如何压缩和报告
如何使用 WorkManager 或替代方案在 Android 13 和 14 中安排定期后台任务?
我目前正在开发一个 Android 应用程序,我需要安排定期后台任务在运行 Android 13 和 14 的设备上每小时运行一次。我尝试过将 WorkManager 与 periodicWorkR 结合使用...
我正在尝试获取托管在 FTP 服务器上的文件的大小,并将其放入标签中,同时“BackgroundWorker”在后台工作。 我使用“尝试”来获取该值,但该值是
我正在更新一个 C# WPF 项目,该项目以前使用 WCF 服务,现在调用基于 REST 的 API。 以下代码是 REST API 调用的典型示例: 公共静态异步任务 我正在更新一个 C# WPF 项目,该项目之前使用 WCF 服务,现在调用基于 REST 的 API。 以下代码是 REST API 调用的典型示例: public static async Task<List<KBase>> GetKbase(int shopID) { // set request string uri = ROOT_URI + "kbase/" + shopID.ToString(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_token.token); // get HttpResponseMessage response = await http_client.SendAsync(request); if (response.IsSuccessStatusCode) { string result = response.Content.ReadAsStringAsync().Result; List<KBase> kb = JsonConvert.DeserializeObject<List<KBase>>(result); return kb; } else { string result = response.Content.ReadAsStringAsync().Result; gFunc.AddLogEntry("Get Kbase: " + result); } return null; } 如果我使用以下代码调用上述 API 方法,一切都会按预期发生。消息框显示 true。 private async void btnTest_MouseUp(object sender, MouseButtonEventArgs e) { List<Models.API.KBase> kb = await apiSamadhi.GetKbase(1); bool is_data = !(kb == null); MessageBox.Show(is_data.ToString()); } 但是,程序的许多部分我都使用后台工作人员来保持主 UI 线程的响应能力。我创建后台工作者如下: BackgroundWorker bgw; List<Models.API.KBase> kb; private void InitBGW() { bgw = new BackgroundWorker(); bgw.DoWork += bgw_DoWork; bgw.RunWorkerCompleted += bgw_WorkCompleted; } 以下代码显示了 DoWork 和 WorkCompleted 方法: private async void bgw_DoWork(object sender, DoWorkEventArgs e) { kbase = await apiSamadhi.GetKbase(1); } private void bgw_WorkCompleted(object sender, RunWorkerCompletedEventArgs e) { bool is_data = !(kbase == null); MessageBox.Show(is_data.ToString()); System.Threading.Thread.Sleep(1000); is_data = !(kbase == null); MessageBox.Show(is_data.ToString()); } 当 bgw_WorkCompleted 运行时,kbase 为 null,第一个消息框显示 false。然后,在线程休眠一秒钟后,kbase不为空,第二个消息框显示true。 这不是我所期望的行为。就像 bgw_DoWork 中的 await 不起作用一样。为什么 bgw_WorkCompleted 在对 API 的“等待”调用完成之前运行? 我错过了什么或者做了什么愚蠢的事情吗?我需要能够在非 UI 线程上运行“等待”API 调用/任务,并能够在任务完成时更新 UI。 尽管遵循了建议的链接并阅读了有关后台工作人员、异步和等待的更多信息,但我仍然在努力寻找可行的解决方案。 考虑到后台工作人员已经老了,不建议与 Async 和 Await 一起使用,我尝试使用 Task.Run 方法。但是,在到达方法末尾之前,所谓的“等待”任务仍未完成。 在下面的代码中,id是静态通用帮助器类中的全局int变量。 static public async void ReloadData() { id = 0; await Task.Run(() => InitialiseDaysheet()); MessageBox.Show(id.ToString()); await Task.Run(() => LoadDaysheet()); MessageBox.Show(id.ToString()); // update ui after loading data } 当上述方法运行时,第一个消息框显示“0”,尽管 InitialiseDaysheet() 末尾的代码分配了值 50。第二个消息框显示“50”,但 LoadDaysheet() 末尾分配了值为 100。 InitialiseDaysheet() 和 LoadDaysheet 有很多代码,但每个方法内都有各种 API 调用,如下所示。 static private async void InitialiseDaysheet() { // code kb = await apiSamadhi.GetKbase(1); // code } 此外,添加如下所示的ConfigureAwait(false)也没有什么区别。 static private async void InitialiseDaysheet() { // code kb = await apiSamadhi.GetKbase(1).ConfigureAwait(false); // code } BackgroundWorker 希望 DoWork 处理程序阻塞,但在 async void 的情况下,它会在实际异步操作完成并调用 WorkCompleted 处理程序之前退出 - 这里真正的工作只是 starting 异步操作,而不是等待它完成。 BackgroundWorker 与 async/await 配合不佳。 你可以完全放弃BackgroundWorker,这样的事情应该可以解决问题: private async void InitBGW() { var kbase = await Task.Run(async () => await apiSamadhi .GetKbase(1) .ConfigureAwait(false)); var is_data = kbase is not null; MessageBox.Show(is_data.ToString()); } 此外,由于我们这里有一个 GUI 应用程序,因此它会有一个 SynchronizationContext,这意味着所有非 UI 相关代码都应该使用 ConfigureAwait(false) 以避免返回 UI 线程: await http_client.SendAsync(request).ConfigureAwait(false); 等待后与UI交互时不需要添加ConfigureAwait: await Task.Run(/* ... */); // no ConfigureAwait() here - get back on UI thread after MessageBox.Show("good, back to UI thread"); 正如有人在评论中提到的,当您已经在 Task<T>.Result 方法中时,没有理由调用 async: string result = await response.Content .ReadAsStringAsync() .ConfigureAwait(false); 如果忘记了 ConfigureAwait,您可以返回 UI 线程,并且 .Result 调用将简单地阻止它。 最后一点 - 您并不总是需要将所有内容包装在 Task.Run() 中 - 仅当异步操作具有长时间执行的同步前缀时,这里可能不是这种情况 - 您可以简单地使用 var data = await apiSamadhi.GetKbase(1); 如果您小心使用 ConfigureAwait() 并且不要在 UI 线程上调用 Task<T>.Result。 将方法声明为 async void 明确声明它不能被等待 - 您需要一些可等待的东西,例如 Task,以便能够跟踪方法完成情况: static private async Task InitialiseDaysheet() { // code kb = await apiSamadhi.GetKbase(1); // code } 如前所述,Task.Run() 不是必需的 - 它用于更紧密地模仿 BackgroundWorker 的行为。 // this one might also be better with changing to async Task, // but hard to tell from the provided example, depends on usage static public async void ReloadData() { id = 0; await InitialiseDaysheet(); MessageBox.Show(id.ToString()); await LoadDaysheet(); MessageBox.Show(id.ToString()); } async void 通常与事件处理程序一起使用,因为 async 不会更改方法签名: // same signature as without async, but now we can await // and still be a valid button click handler async void OnButtonClick(object? sender, EventArgs e) { try { await MyAsyncCall(); } catch(Exception exc) { MessageBox.Show(exc.Message); // if we dont handle exceptions in async void - nobody will // because nobody can await this call - it looks like a normal // sync method to the external observer } } 并且 ConfigureAwait(false) 与等待调用的能力无关 - 它只影响任务继续运行的线程的选择: async void A() { System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.ManagedThreadId); await SomeAsyncMethod(); System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.ManagedThreadId); // back to UI thread if A() was called from UI thread } async void B() { System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.ManagedThreadId); await SomeAsyncMethod().ConfigureAwait(false); System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.ManagedThreadId); // continue on a thread pool thread, don't go back to UI thread }
我正在更新一个 C# WPF 项目,该项目以前使用 WCF 服务,现在调用基于 REST 的 API。 以下代码是 REST API 调用的典型示例: 公共静态异步任务 我正在更新一个 C# WPF 项目,该项目之前使用 WCF 服务,现在调用基于 REST 的 API。 以下代码是 REST API 调用的典型示例: public static async Task<List<KBase>> GetKbase(int shopID) { // set request string uri = ROOT_URI + "kbase/" + shopID.ToString(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_token.token); // get HttpResponseMessage response = await http_client.SendAsync(request); if (response.IsSuccessStatusCode) { string result = response.Content.ReadAsStringAsync().Result; List<KBase> kb = JsonConvert.DeserializeObject<List<KBase>>(result); return kb; } else { string result = response.Content.ReadAsStringAsync().Result; gFunc.AddLogEntry("Get Kbase: " + result); } return null; } 如果我使用以下代码调用上述 API 方法,一切都会按预期发生。消息框显示 true。 private async void btnTest_MouseUp(object sender, MouseButtonEventArgs e) { List<Models.API.KBase> kb = await apiSamadhi.GetKbase(1); bool is_data = !(kb == null); MessageBox.Show(is_data.ToString()); } 但是,程序的许多部分我都使用后台工作人员来保持主 UI 线程的响应能力。我创建后台工作者如下: BackgroundWorker bgw; List<Models.API.KBase> kb; private void InitBGW() { bgw = new BackgroundWorker(); bgw.DoWork += bgw_DoWork; bgw.RunWorkerCompleted += bgw_WorkCompleted; } 以下代码显示了 DoWork 和 WorkCompleted 方法: private async void bgw_DoWork(object sender, DoWorkEventArgs e) { kbase = await apiSamadhi.GetKbase(1); } private void bgw_WorkCompleted(object sender, RunWorkerCompletedEventArgs e) { bool is_data = !(kbase == null); MessageBox.Show(is_data.ToString()); System.Threading.Thread.Sleep(1000); is_data = !(kbase == null); MessageBox.Show(is_data.ToString()); } 当 bgw_WorkCompleted 运行时,kbase 为 null,第一个消息框显示 false。然后,在线程休眠一秒钟后,kbase不为空,第二个消息框显示true。 这不是我所期望的行为。就像 bgw_DoWork 中的 await 不起作用一样。为什么 bgw_WorkCompleted 在对 API 的“等待”调用完成之前运行? 我错过了什么或者做了什么愚蠢的事情吗?我需要能够在非 UI 线程上运行“等待”API 调用/任务,并能够在任务完成时更新 UI。 BackgroundWorker 希望 DoWork 处理程序阻塞,但在 async void 的情况下,它会在实际异步操作完成并调用 WorkCompleted 处理程序之前退出 - 这里真正的工作只是 starting 异步操作,而不是等待它完成。 BackgroundWorker 与 async/await 配合不佳。 你可以完全放弃BackgroundWorker,这样的事情应该可以解决问题: private async void InitBGW() { var kbase = await Task.Run(async () => await apiSamadhi .GetKbase(1) .ConfigureAwait(false)); var is_data = kbase is not null; MessageBox.Show(is_data.ToString()); }
Backgroundworker CancelAsync() 不起作用
我正在尝试使用 WorkerClass.bw.CancelAsync() 取消我的后台工作程序。但这根本行不通。 //编辑!我在这里发布了完整的代码。希望这会有所帮助。 好吧,我添加了一些消息框来了解...
我正在实现后台服务,问题是当我在本地运行它时,它工作正常,因为应用程序已启动并正在运行。但在iis中我部署了代码并在iis中启动了服务器。
我有一个作为 Windows 服务运行的 C# 控制台应用程序。它实现了BackgroundService,这是实现Windows 服务的推荐方法。 另外,我正在使用 Hangfire 来启动...
我编写了缓存更新功能。 这是我的 Redis 缓存实现: 公共类RedisCache:ICache { 私有只读 IDatabase _cache; 公共 RedisCache(字符串