Sök…


Åtkomst till formkontroller från andra trådar

Om du vill ändra ett attribut för en kontroll, till exempel en textruta eller etikett från en annan tråd än GUI-tråden som skapade kontrollen, måste du åberopa den, annars kan du få ett felmeddelande om:

"Cross-thread operation not valid: Control 'control_name' nås från en annan tråd än tråden den skapades på."

Att använda detta exempelkod på ett system.windows.forms-formulär kommer att göra ett undantag med det meddelandet:

private void button4_Click(object sender, EventArgs e)
{
    Thread thread = new Thread(updatetextbox);
    thread.Start();
}

private void updatetextbox()
{
    textBox1.Text = "updated"; // Throws exception
}

När du istället vill ändra en textboxs text från en tråd som inte äger den använder du Control.Invoke eller Control.BeginInvoke. Du kan också använda Control.InvokeRequired för att kontrollera om man kräver kontrollen.

private void updatetextbox()
{
    if (textBox1.InvokeRequired)
        textBox1.BeginInvoke((Action)(() => textBox1.Text = "updated"));
    else
        textBox1.Text = "updated";
}

Om du behöver göra detta ofta kan du skriva ett tillägg för obearbetbara objekt för att minska mängden kod som krävs för att göra denna kontroll:

public static class Extensions
{
    public static void BeginInvokeIfRequired(this ISynchronizeInvoke obj, Action action)
    {
        if (obj.InvokeRequired)
            obj.BeginInvoke(action, new object[0]);
        else
            action();
    }
}

Och att uppdatera textrutan från valfri tråd blir lite enklare:

private void updatetextbox()
{
    textBox1.BeginInvokeIfRequired(() => textBox1.Text = "updated");
}

Var medveten om att Control.BeginInvoke som används i detta exempel är asynkron, vilket innebär att kod som kommer efter ett samtal till Control.BeginInvoke kan köras omedelbart efter, oavsett om den godkända delegaten har utförts eller inte.

Om du måste vara säker på att textBox1 uppdateras innan du fortsätter använder du Control.Invoke istället, vilket kommer att blockera samtalstråden tills din delegat har körts. Observera att det här tillvägagångssättet kan bromsa din kod betydligt om du gör många anropar samtal och notera att det kommer att låsa upp din applikation om din GUI-tråd väntar på att samtalstråden ska slutföra eller släppa en innehöll resurs.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow