我知道它有3种方法.在我的程序中,我有一个发送消息的方法.这通常很晚,程序有时根本不响应按钮按下发送消息.有时它比我期望的晚5秒,程序冻结.我想使用a BackgroundWorker按预期发送消息,并允许程序始终正常运行.我有用于在按钮处理程序中发送消息的代码.现在我在哪里放这个等效的代码?我希望所有这些仍然可以通过按钮按下来处理.
这是合适的处理程序吗?
backgroundWorker1.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)
并在:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {}
Run Code Online (Sandbox Code Playgroud)
我要把我的代码放在按钮处理程序中?而这之前:
carga.progressBar1.Minimum = 0;
carga.progressBar1.Maximum = 100;
Run Code Online (Sandbox Code Playgroud)
Carga是ProgressBar的另一种形式.如何在此方案中使用BackgroundWorker?
我有一个有2个组合框的表格.我想combobox2.DataSource基于combobox1.Text和填充combobox2.Text(我假设用户已完成输入combobox1并且正在输入中combobox2).所以我有一个这样的事件处理程序combobox2:
private void combobox2_TextChanged(object sender, EventArgs e)
{
if (cmbDataSourceExtractor.IsBusy)
cmbDataSourceExtractor.CancelAsync();
var filledComboboxValues = new FilledComboboxValues{ V1 = combobox1.Text,
V2 = combobox2.Text};
cmbDataSourceExtractor.RunWorkerAsync(filledComboboxValues );
}
Run Code Online (Sandbox Code Playgroud)
至于构建DataSource是一个耗时的过程(它创建一个对数据库的请求并执行它)我决定使用BackgroundWorker在另一个进程中执行它更好.因此,当cmbDataSourceExtractor尚未完成其工作并且用户再键入一个符号时,会出现这种情况.在这种情况下,我在这一行上得到一个例外,
cmbDataSourceExtractor.RunWorkerAsync(filledComboboxValues );说明BackgroundWorker正忙,无法同时执行多个操作.
如何摆脱这种异常?
提前致谢!
我正在编写一个Windows应用程序,它反复运行一系列数字IO操作.
当用户单击"开始"按钮时,此操作序列开始,并由后台工作人员在backgroundWorker1_DoWork()中完成.
但是,有时候我得到"这个背景工作者当前很忙......."的错误信息.
我正在考虑在代码中实现以下内容,通过使用while循环来"杀死"后台工作程序,然后再启动另一个操作序列:
if (backgroundWorker1.IsBusy == true)
{
backgroundWorker1.CancelAsync();
while (backgroundWorker1.IsBusy == true)
{
backgroundWorker1.CancelAsync();
}
backgroundWorker1.Dispose();
}
backgroundWorker1.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)
我认为我主要担心的是,backgroundWorker1最终会被"杀死"吗?如果愿意,需要很长时间才能完成吗?
这种编码会让我陷入无限循环吗?
我需要RunWorkerAsync()回报一个List<FileInfo>.如何从后台工作者返回一个对象?
只想就多线程任务的"最佳实践"提出一些建议.
例如,我们有一个C#应用程序,它在启动时从我们数据库中的各种"类型"表中读取数据,并将信息存储在我们传递给应用程序的集合中.这可以防止我们每次需要此信息时都会访问数据库.
此时应用程序正在同步读取10个表中的数据.我真的希望从一个并行运行的不同线程中的每个表中读取应用程序.在继续启动应用程序之前,应用程序将等待所有线程完成.
我已经研究过BackGroundWorker但只是想要一些关于完成上述工作的建议.
我期待着一些答案
这是处理BackGroundWorker的正确方法吗?我不确定在调用.Dispose()之前是否需要删除事件.还在RunWorkerCompleted委托中调用.Dispose()确定吗?
public void RunProcessAsync(DateTime dumpDate)
{
BackgroundWorker worker = new BackgroundWorker();
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync(dumpDate);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
// Do Work here
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
worker.Dispose();
}
Run Code Online (Sandbox Code Playgroud) 如果我单击一个启动backgroundworker两次的按钮,我会收到此错误.
This BackgroundWorker is currently busy and cannot run multiple tasks concurrently
Run Code Online (Sandbox Code Playgroud)
我怎么能避免这个?
我花了一整天的时间试图让我的应用程序使用线程,但没有运气.我已经阅读了很多关于它的文档,我仍然会遇到很多错误,所以我希望你能帮助我.
我有一个耗时的方法,它调用数据库并更新GUI.这必须一直发生(或大约每30秒).
public class UpdateController
{
private UserController _userController;
public UpdateController(LoginController loginController, UserController userController)
{
_userController = userController;
loginController.LoginEvent += Update;
}
public void Update()
{
BackgroundWorker backgroundWorker = new BackgroundWorker();
while(true)
{
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerAsync();
}
}
public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
_userController.UpdateUsersOnMap();
}
}
Run Code Online (Sandbox Code Playgroud)
使用这种方法我得到一个例外,因为后台工作者不是和STA线程(但从我可以理解这是我应该使用的).我试过一个STA线程,并给出了其他错误.
我认为问题是因为我在进行数据库调用时尝试更新GUI(在后台线程中).我应该只进行数据库调用,然后以某种方式它应该切换回主线程.在主线程执行后,它应该返回后台线程,依此类推.但我看不出怎么做.
应用程序应在数据库调用后立即更新GUI.Firering事件似乎不起作用.背景线程只是输入它们.
编辑:
一些非常好的答案:)这是新的代码:
public class UpdateController{
private UserController _userController;
private BackgroundWorker _backgroundWorker;
public UpdateController(LoginController loginController, UserController userController)
{
_userController = userController;
loginController.LoginEvent += Update;
_backgroundWorker = new BackgroundWorker(); …Run Code Online (Sandbox Code Playgroud) 请注意以下代码:
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
Run Code Online (Sandbox Code Playgroud)
现在假设我想等到bw完成工作.这样做的正确方法是什么?
我的解决方案是:
bool finished = false;
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
OnAsyncOperationCompleted(sender, args);
finished = true;
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
int timeout = N;
while (!finished && timeout > 0)
{
Thread.Sleep(1000);
--timeout;
}
if (!finished)
{
throw new TimedoutException("bla bla bla");
}
Run Code Online (Sandbox Code Playgroud)
但我不喜欢它.
我已经考虑用finished同步事件替换标志,在RunWorkerCompleted处理程序中设置它并在以后阻塞它而不是执行while-sleep循环.
唉,这是错误的,因为代码可能在WPF或WindowsForm同步上下文中运行,在这种情况下,我会阻止与 …
我用过这段代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
namespace WindowsApplication1 {
public partial class Form1 : Form {
// Class to report progress
private class UIProgress {
public UIProgress(string name_, long bytes_, long maxbytes_) {
name = name_; bytes = bytes_; maxbytes = maxbytes_;
}
public string name;
public long bytes;
public long maxbytes;
}
// Class to report exception {
private class UIError {
public UIError(Exception ex, string path_) {
msg = ex.Message; path = path_; …Run Code Online (Sandbox Code Playgroud) backgroundworker ×10
c# ×9
.net ×3
winforms ×2
asynchronous ×1
concurrency ×1
file-copying ×1
file-io ×1
progress-bar ×1
wpf ×1