我尝试寻找解决方案,但没有任何效果,所以我直接询问。我正在使用
BackGroundWorker
,当我绘制位图时,我想在 PictureBox
中显示它。这看起来很棘手,所以至少我想在标签中显示进度百分比,但标签在此过程中不会更新。
Work 调用一个传递参数(一个位图和一个字符串)的函数。为了显示标签中的值,我将使用
ProgressChange
事件(这也是您所期望的,因为它在 MS Docs 示例中逐字说明)。在活动期间,我正在这样做:
uint dimen = (uint)pbo.Width * (uint)pbo.Height;
uint count = 0;
Bitmap pbn = new Bitmap(pbo, new Size(pbo.Width * 2, pbo.Height * 2));
for loop (some values)
{
//do stuff
count++;
backgroundWorker1.ReportProgress((int)((count / dimen) * 100), text);
}
for loop (other values)
{
//do stuff
count++;
backgroundWorker1.ReportProgress((int)((count / dimen) * 100), text);
}
for loop (other values)
{
//do stuff
count++;
backgroundWorker1.ReportProgress((int)((count / dimen) * 100), text);
}
从字面上看,进度事件只是调用
label1.Text = $"{e.UserState} {e.ProgressPercentage}%";
。无论您在这段代码中没有看到什么,都没关系。这主要是不起作用的部分。
BGW 的报告功能设置为 true(实际上它有点工作,但不像我预期的那样,因为它似乎工作得很慢,这意味着不在我的功能期间,或者根本不工作)。
我知道我不清爽。我不明白为什么我应该这样做,因为 MS Docs 不这样做。如果我在设置标签内容后尝试刷新标签,则会收到此错误:
完整错误消息:
托管调试助手“DisconnectedContext”:“此 RuntimeCallableWrapper 转换到 COM 上下文 0xad4f80 失败,并出现以下错误:由于应用程序正在分派输入同步调用,因此无法进行传出调用。 (HRESULT 异常:0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL))。这通常是因为创建此 RuntimeCallableWrapper 的 COM 上下文 0xad4f80 已断开连接,或者它正忙于执行其他操作而无法处理上下文转换。不会使用代理来服务 COM 组件上的请求,并且将直接对 COM 组件进行调用。这可能会导致损坏或数据丢失。为了避免这个问题,请确保所有 COM 上下文/单元/线程都保持活动状态并且可用于上下文转换,直到应用程序完全使用代表其中存在的 COM 组件的 RuntimeCallableWrappers 完成。
关于如何更改代码并仍然保持这种结构有什么想法吗?我还意味着继续使用
BGW
。
我将报告限制为
if (count % 100 == 0)
,并且我还尝试将标签文本更改为label1.Invoke(new Action(() => { label1.Text = $"{e.UserState} {e.ProgressPercentage}%"; }));
我的问题的一部分还在于我根据常识错误地判断了计算。让变量为 uint 使得 (a / b) 等于 0 直到进程结束,因此传递给报告器的值始终为 0 * 100 直到达到 1 * 100 (所以基本上我读取 0% 直到达到 100% )。相反,我通过了 count * 100 / dimen 并且它有效。
我还尝试了一种解决方案来显示填充每个像素的
PictureBox
,但我发现这是一个非常缓慢的过程,因为我认为有两种方法,但我认为它们都需要刷新:一种是时不时地设置(也许每1000像素之后?)PictureBox.Image = //temporary filled Bitmap
但这使得图像每次刷新时都会闪烁,而另一个实际上不是设置完整图像,而是只绘制单个像素,而不能每1000像素完成一次(因为它不是结果的实际实时显示)并且实际上需要对每个像素进行操作;不确定这是否可以避免眨眼,但肯定会需要/浪费更多时间。所以现在我放弃了显示图像填充的想法,这是一个好主意,但我更喜欢性能而不是花哨的想法。