Zoeken…


Toegang tot formulierbesturingselementen vanuit andere threads

Als u een kenmerk van een besturingselement, zoals een tekstvak of label, wilt wijzigen van een andere thread dan de GUI-thread die het besturingselement heeft gemaakt, moet u dit inschakelen of krijgt u mogelijk een foutbericht met de melding:

"Cross-thread bewerking niet geldig: controle 'control_name' benaderd vanuit een andere thread dan de thread waarop het is gemaakt."

Als u deze voorbeeldcode op een formulier system.windows.forms gebruikt, wordt een uitzondering met dat bericht gegenereerd:

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

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

Gebruik in plaats daarvan Control.Invoke of Control.BeginInvoke wanneer u de tekst van een tekstvak wilt wijzigen vanuit een thread waarvan het geen eigenaar is. U kunt ook Control.InvokeRequired gebruiken om te controleren of het nodig is het besturingselement op te roepen.

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

Als u dit vaak moet doen, kunt u een extensie schrijven voor aanroepbare objecten om de hoeveelheid code te verminderen die nodig is om deze controle uit te voeren:

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

En het bijwerken van het tekstvak vanuit elke thread wordt een beetje eenvoudiger:

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

Houd er rekening mee dat Control.BeginInvoke zoals gebruikt in dit voorbeeld asynchroon is, wat betekent dat code die na een aanroep van Control.BeginInvoke komt, onmiddellijk daarna kan worden uitgevoerd, ongeacht of de doorgegeven deelnemer al dan niet is uitgevoerd.

Als u zeker wilt weten dat textBox1 is bijgewerkt voordat u doorgaat, gebruikt u in plaats daarvan Control.Invoke, die de aanroepende thread blokkeert totdat uw gemachtigde is uitgevoerd. Houd er rekening mee dat deze aanpak uw code aanzienlijk kan vertragen als u veel aanroepen uitvoert en dat uw toepassing vastloopt als uw GUI-thread wacht op de aanroepende thread om een vastgehouden bron te voltooien of vrij te geven.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow