在C#中需要代码说明

时间:2010-10-20 11:12:38

标签: c#

我需要逐行详细解释以下代码以及流程如何,例如,当我调试时。我刚刚在我的程序中使用了这段代码来避免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");

我还需要代表们的解释。我读到了它,但我理解的是委托就像一个函数的指针,但我需要一个简单的例子清晰的解释。把我想成一个新手。

5 个答案:

答案 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线程运行一些代码来更新文本框的值,因为当前线程无法执行此操作。

总结一下,

  • 代理是包含执行此操作的说明的代码,
  • UI线程是什么,
  • 您的线程通过Invoke方法要求UI线程执行此操作。

也读了 Control.InvokeRequired Property

答案 4 :(得分:2)

委托就像是指向函数的指针(我希望你知道C中的函数指针)。因此委托应该具有与函数相同的签名,以便您可以指向它。

跨线程调用仅在.NET Framework 1.1中允许。它在2.0之后已经停止,因此应用程序使用 txtDelegate.InvokeRequired检查此调用是否是跨线程调用或正常调用,并让代表调用方法而不是真正的调用.....

否则,我们可以进行正常的更改(相同的线程)。