- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有两个文件。一个包含 DataProgressBar 类型的变量并在加载其自己的组件之前调用 startAsyncWorker() 方法。另一个是下面显示的 DataProgressBar。当我运行我的程序并在其他文件中调用 startAsyncWorker() 时,行为
预期:显示带有进度条的小窗口,在执行 WorkerDatabaseInsertion 时从 0 加载到 100。然后,当完成包含 DataProgressBar 的第一个类文件时,将继续执行下一条指令。
已体验:显示带有进度条的小窗口,未对 UI 进行任何更改,线程似乎卡住,因为未显示输出或处理证据。我关闭窗口,调用文件恢复。
public partial class DataProgressBar : Window
{
private BackgroundWorker bgw;
private String _path;
private LFPReader _lfp;
private Access db;
public DataProgressBar(String p, LFPReader reader, Access database)
{
InitializeComponent();
/* Set private class level variables */
_path = p;
_lfp = reader;
db = database;
db.open();
/* Set up worker and progressbar */
bgw = new BackgroundWorker();
SetUpWorker(bgw);
progressbar.Maximum = 100;
progressbar.Minimum = 0;
progressbar.Value = 0;
}
public void startAsyncWorker()
{
if(bgw.IsBusy != true)
{
bgw.RunWorkerAsync();
}
}
/// <summary>
/// This methods exists for completeness, but we will
/// probably not need to directly cancel the worker from here.
/// --Kurtpr
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void cancelAsyncWorker(object sender, EventArgs e)
{
if (bgw.WorkerSupportsCancellation == true)
{
bgw.CancelAsync();
}
}
private void SetUpWorker(BackgroundWorker worker)
{
worker.WorkerReportsProgress = true; // we need this in order to update the UI
worker.WorkerSupportsCancellation = true; // Not sure why, but we may need this to cancel
worker.DoWork += new DoWorkEventHandler(WorkerDatabaseInsertion);
worker.ProgressChanged += new ProgressChangedEventHandler(WorkerProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerBurnNotice);
}
private void WorkerDatabaseInsertion(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = sender as BackgroundWorker;
ImageInfo ImageData = new ImageDB.ImageInfo();
double size = _lfp.GetImageData().ToArray().Length;
int index = 0;
//_path is setup in loadAsLFP() before this call.
foreach (var image in _lfp.GetImageData())
{
index++;
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
image.FullPath = Path.Combine(_path, image.FullPath);
ImageData.Add(new ImageDB(image));
db.insertImage(new ImageDB(image));
worker.ReportProgress((int)(index/size));
}
}
private void WorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("Hello");
progressbar.Value = e.ProgressPercentage;
}
private void WorkerBurnNotice(object sender, RunWorkerCompletedEventArgs e)
{
db.close();
}
}
我怀疑我对 BackgroundWorker 的一个基本方面是错误的。我的逻辑错误在哪里?
编辑 下面是调用和创建 DataProgressBar 对象的代码。
private void createDb(string filePath, LFPReader lfp)
{
//Set up LFP related objects.
ImageData = new ImageDB.ImageInfo();
//create database file.
filePath = filePath.Replace(".lfp", ".mdb").Replace(".LFP", ".mdb");
_lfpName = filePath; // update to use the database file
Access db = new Access(filePath.Replace(".lfp", ".mdb"));
db.createDatabase();
//used for calculating progress of creating this new database.
var progressbar = new DataProgressBar(_path, lfp, db);
progressbar.ShowDialog();
progressbar.startAsyncWorker();
CurImage = ImageData.First().FullPath;
//Make sure that data context is set for these images.
DataContext = ImageData;
}
最佳答案
我认为你的进度计算逻辑在这里有问题。
worker.ReportProgress((int)(index/size));
此行将始终报告进度为 0。因此,您的进度条将始终停留在 0 位置。
相反,使用以下以百分比形式报告进度。
worker.ReportProgress((int)(index*100/size));
更新:您共享的代码似乎是正确的。我认为问题在于您实现进度条的方式。
我想你正在从主线程调用 startAsyncWorker 方法,如下所示;
var dpb = new DataProgressBar(p, reader, database);
dpb.startAsyncWorker();
调用以上两行后,您的主线程应该是空闲的。
这意味着,以下代码将导致您的进度条卡住 50 秒,因为即使您的 DoWork 运行完美,UI 也不会更新,因为主线程没有空闲。
var dpb = new DataProgressBar(p, reader, database);
dpb.startAsyncWorker();
Thread.Sleep(50000); //Main thread is busy for 50 seconds
更新 2:
真正的问题在于以下几行;
var progressbar = new DataProgressBar(_path, lfp, db);
progressbar.ShowDialog();
progressbar.startAsyncWorker();
实际上 ShowDialog()
方法将 DataProgressBar
显示为模态对话框。这意味着,除非您关闭该对话框,否则控件不会转到下一行。
您的问题应使用以下代码解决;
var progressbar = new DataProgressBar(_path, lfp, db);
progressbar.startAsyncWorker();
progressbar.ShowDialog();
它将首先启动您的后台工作程序,然后将显示 DataProgressBar 对话框。
关于C# BackgroundWorker 和 ProgressBar 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42129391/
在我的应用程序中,我在添加到我的列表框之前通过打开的 Wireshark 进程检查我的文件。这是添加目录单击事件,它获取根文件夹并检查此文件夹和子文件夹中的所有文件: private void btn
我有一个使用异步后台工作程序执行批处理文件的程序。这是代码: public static void Execute(CmdObj obj, bool batch) { CmdObj = obj
我正在尝试在项目中执行数据库密集型任务。这是一个演练: 我们需要搜索我们的 worker 数据库,我们称之为 Locums,并找到一个适合特定工作的人。当我们决定处理 x 个作业时,此过程开始。因此,
首先,我还是个初学者,如果您能耐心一点,我将不胜感激:) 今天我一直在为这件事绞尽脑汁。 问题是,我想运行三个不同的后台程序。但是我想等到一个运行完再运行下一个,依此类推。 每个后台 worker 都
我需要确保 BackgroundWoker 在被调用之前不忙,所以我检查 IsBusy 并调用 CancelAsync如果是: if (bgWorker.IsBusy)
我的目标是: 用户在组合框中输入完整或部分计算机名 按钮单击事件启动后台工作程序将计算机名传递给 DoWork 方法 DoWork 方法在 ActiveDirectory 中搜索计算机名并将集合传递给
每次我的代码需要与网络或数据库通信时,我都会使用后台工作人员,我是否可以使用太多,执行这些任务的正确方法是什么? 如果我不使用后台工作程序,则在远程主机关闭等情况下,gui会锁定,因此使用后台工作程序
关于 BGW 长期运行的任何想法建议? 最佳答案 是的 :)。在 BackgroundWorker 或 ThreadPool 中进行长时间运行的操作并没有本质上的错误……如果由于长时间运行的操作而导致
学习构建多线程 WPF 应用程序我读到了一些使用 BackgroundWorker 的限制,这对我来说不是很清楚。请帮我理解: 如果我不仅想要一个线程在 UI 的幕后工作,而且可能有多个线程,它们彼此
问题:重新使用 .NET Backgroundworker,有没有办法让异常正常传递回主线程? 背景: 目前在我的 WinForms 应用程序中,我有通用异常句柄,如果(a)自定义应用程序异常然后呈现
在尝试实现一个简单的 BackgroundWorker 时,我遇到了臭名昭著的“跨线程操作无效”异常。我花了几个小时阅读我能找到的关于这个主题的所有内容,包括关于 SO 的许多相关问题,但我就是不明白
有没有办法缩短我的 BackgroundWorker.CancellationPending 检查点? 例如,有没有办法像下面的示例代码一样封装return: //REAL CODE (CURRENT
嗨,我在处理完成后,无法将在BackgroundWorker的DoWork处理程序内部生成的图像数据分配给图像对象。我收到一条错误消息,指出“调用线程无法访问此对象,因为其他线程拥有它”。错误行是 P
如何获得有意义的BackgroundWorker.Error当DoWork必须调用可能引发异常的委托(delegate)? 我正在实现一个静态 MsgBox公开向用户传达自定义消息的各种方式(使用自定
我知道您可以在首次启动 backgroundworker 时通过 RunWorkerAsync 函数调用传递参数,但是您可以在它已经启动后向它传递数据吗?或者我是否需要创建自己的并发形式来处理从不同线
我有一个风格问题,关于我应该在 Windows 窗体应用程序上使用的后台线程实现的选择。目前,我的表单上有一个 BackgroundWorker,它具有无限 (while(true)) 循环。在此循环
我正在尝试在 .NET 1.1 中实现一个 BackgroundWorker(因为没有任何东西),而且我不太精通线程和委托(delegate)。 现在我有一个名为 BackgroundWorker 的
foreach (string file in listToConvert) { BackgroundWorker backgroundWorker = new BackgroundWorke
我正在制作我的第一个 C# GUI。它使用 BackgroundWorker 来运行计算量大的模拟。模拟会定期报告(通过 ProgressChanged 事件)需要在 GUI 中显示的大量信息。 GU
我想从一个表单启动一个后台 worker 。 private void button2_Click(object sender, EventArgs e) { back
我是一名优秀的程序员,十分优秀!