【发布时间】:2015-12-08 08:20:35
【问题描述】:
我正在运行一个BackgroundWorker,它应该会更新我的UserControl。我在检查InvokeRequired 属性后尝试调用:
private void bgwHighlightText_DoWork(object sender, DoWorkEventArgs e)
{
tmpRich.SelectedRtf = myRtf;
if (_ucResultRich.InvokeRequired && _ucResultRich.rchResult.InvokeRequired)
_ucResultRich.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf)); // Debug pointer stops here
//Rest of the code
}
我还尝试直接在我的UserControl 中调用RichTextBox:
_ucResultRich.rchResult.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf));
但是当我调试代码时,它只是停止运行其余代码而没有错误。
_ucResultRich.InvokeRequired 和 _ucResultRich.rchResult.InvokeRequired 都返回 true。
我在这里做错了吗?
更新
我将Invoke 部分放在try catch 中,现在我可以从异常消息中得到以下错误:
Cross-thread operation not valid: Control '' accessed from a thread
other than the thread it was created on.
是因为它无法确定控件吗?因为它显示为Control ''。
【问题讨论】:
-
backgroundworker 的重点在于轻松创建 2 个线程:一个用于 GUI,另一个用于其他东西。它包括在两个线程之间完美通信所需的所有内容,但您必须正确使用它。
DoWork事件启动后台工作线程,因此,您无法从那里修改属于 GUI 线程的内容(例如,任何控件)。要在控件中执行任何修改,您应该等待后台工作线程完成(通过RunWorkerCompleted事件)或调用WorkerReportsProgress(+ 知道如何使用它)... -
... 总之:您应该学会正确使用 backgroundworker 或根本不使用它(还有其他多线程方法)。您正在尝试的 (
Invoke) 没有任何意义:您正在混合使用不同的方法(并没有最大化使用后台工作程序的主要原因,其内置功能的简单性)通常会导致错误永远不会发生(= 未正确使用给定变量的结果)。 -
你是在为做错事辩护吗?!如前所述:您错误地使用了后台工作程序;并且您尝试解决错误(+建议的解决方案)并没有太大意义。 backgroundworker 具有内置事件以允许两个线程之间的通信,您应该正确使用它们(= 了解
DoWork的含义/暗示)。如果您不使用 backgroundworker 的内置功能,那么使用它有什么意义呢?!这是一种非常有限的多线程方法(= 只有 2 个线程)。 -
你在说什么!???如果你不知道什么,你为什么不直接问而不是说没有任何意义的事情?! backgroundworker 的重点在于避免 GUI 冻结。这些事件允许 GUI 和后台工作线程之间进行适当的通信。在其他多线程方法中,您必须自己创建所有这些; backgroundwer 内置了所有内容,可以立即使用。
-
说真的?!所以你发现了backgroundworker的多线程方式的一个bug?它不适用于图片框?你不觉得也许你用错了吗?此外,如果您认为,解决方案将很简单:不要使用后台工作程序;使用不同的多线程方法。无论如何……随心所欲。我已经写了足够清晰的 cmets 供未来的读者正确理解这种情况。
标签: c# winforms backgroundworker invoke invokerequired