我需要逐行详细解释以下代码以及流程如何,例如,当我调试时。我刚刚在我的程序中使用了这段代码来避免cross thread access error
。代码工作正常,但这个代码到底是什么?
delegate void updateTextField(string Text);
private void updateText(string Text)
{
if (txtDelegate.InvokeRequired)
{
updateTextField del = new updateTextField(updateText);
txtDelegate.Invoke(del, new object[] { Text });
}
else
{
txtDelegate.Text = Text;
}
}
此方法在backgroundWorker_DoWork()
:
updateText("using delegate");
我还需要代表们的解释。我读到了它,但我理解的是委托就像一个函数的指针,但我需要一个简单的例子清晰的解释。把我想成一个新手。
答案 0 :(得分:13)
// Declaring a delegate function kind of lifts the function away from the
// current object and the current thread, making it 'thread-safe' to call
// (although it may still not be thread-safe to execute).
delegate void updateTextField(string Text);
private void updateText(string Text)
{
// This asks the control if it's running on the same thread as this method is
// currently executing, i.e. can I update you directly or do I need to use
// the cross thread calling method "Invoke".
if (txtDelegate.InvokeRequired)
{
// Here we define the delegate function that's going to be Invoked.
// Here it's the same function were currently within but when it's invoked
// by the following line, it'll be done on the same thread as the control.
// At that point, InvokeRequired will return false and the other branch
// will be followed to update the actual text on the control.
updateTextField del = new updateTextField(updateText);
// Here we invoke the function passing in the Text we want to update the
// control with as a parameter.
txtDelegate.Invoke(del, new object[] { Text });
}
else
{
// When this function is Invoked, this is the branch that will be followed
// (as we're on the same thread as the control) and the text on the control
// will be replaced with the text passed in from the Invoke.
txtDelegate.Text = Text;
}
}
我希望更详细地介绍它,委托的实际机制是“线程安全的”超出了这个答案的范围。
答案 1 :(得分:3)
delegate void updateTextField(string Text); // delegate allows updatetext to be passed as a parameter
private void updateText(string Text)
{
if (txtDelegate.InvokeRequired) // on a different thread so requires invoke
{
updateTextField del = new updateTextField(updateText);
txtDelegate.Invoke(del, new object[] { Text }); // invoke/execute the delegate on the thread
}
else
{
txtDelegate.Text = Text;
}
}
评论已添加到代码中
答案 2 :(得分:3)
从错误的线程调用updateText
时(假设txtDelegate
是一个控件,从其创建的线程(UI线程)以外的任何线程调用),流程如下
updateText(String) called on 'wrong' thread
txtDelegate.InvokeRequired is true
wrap updateText(String) in a delegate (updateTextField)
invoke the delegate on the correct thread (passing Text as parameter)
updateText(String) called on correct thread
txtDelegate.InvokeRequire is false
set txtDelegate.Text to Text
直接在“正确”线程(UI线程)上调用时:
updateText(String) called on correct thread
txtDelegate.InvokeRequire = false
set txtDelegate.Text to Text
答案 3 :(得分:3)
当你说委托就像一个方法的指针时,你会发现。它允许您以安全的方式指定一个方法,'Foo',作为另一个方法的参数,'Bar',并且很有可能,'Bar'方法将在某个阶段调用'Foo'。
在上面的代码中,您需要完成所有这些工作的原因是由于线程。在Windows Forms中,您的应用程序中可能有多个线程,但只允许UI线程对控件进行更改。因此,在txtDelegate.InvokeRequired
行中,您要检查线程是否是UI线程。如果是,那么只需将txtDelegate的值设置为正常(在else
部分中),如果不是,则会变得有点棘手。然后,您需要告诉UI线程运行一些代码来更新文本框的值,因为当前线程无法执行此操作。
总结一下,
答案 4 :(得分:2)
委托就像是指向函数的指针(我希望你知道C中的函数指针)。因此委托应该具有与函数相同的签名,以便您可以指向它。
跨线程调用仅在.NET Framework 1.1中允许。它在2.0之后已经停止,因此应用程序使用 txtDelegate.InvokeRequired检查此调用是否是跨线程调用或正常调用,并让代表调用方法而不是真正的调用.....
否则,我们可以进行正常的更改(相同的线程)。