C # kruiskoppelingen niet geldig, 2 bedieningselementen en 2 afzonderlijke threads

Hier is een vereenvoudigd voorbeeld van wat ik probeer te doen:

I have 2 controls MyControl c and Panel p. p is created in the main GUI thread as normal, but I want c to be created in a background thread, because it takes awhile and I don't want to freeze the GUI. How can I add c to p.Controls? If I do it in this.Invoke it throws an exception for c, and if I do it from the background thread it throws an exception for p.

Of moet ik eigenlijk geen GUI-elementen maken buiten de hoofd-GUI-thread?

2
Helaas is dit een controle van derden met gesloten bronnen. Ik neem aan dat ik even zal kijken of het langzame deel kan worden afgescheiden.
toegevoegd de auteur fred, de bron
Of zou ik eigenlijk geen GUI-elementen moeten maken buiten de hoofd-GUI-thread? - Typisch. Moet u het besturingselement echt maken in een andere thread? Waarom is het zo duur om het te maken? Kun je de besturing niet goedkoop maken en een achtergrondthread gebruiken om het te laden met gegevens of om wat dan ook te doen wat je moet doen?
toegevoegd de auteur Ed S., de bron
Controles die op verschillende threads zijn gemaakt, indien mogelijk, is een recept voor hoofdpijn. Maak ze beide op de UI-thread. Gebruik p.Invoke() om de methode te gebruiken die c creëert.
toegevoegd de auteur Igby Largeman, de bron

3 antwoord

Of moet ik eigenlijk geen GUI-elementen maken buiten de hoofd-GUI-thread?

Ja, dit is eigenlijk het probleem. De meeste besturingselementen hebben thread-affiniteit en moeten worden gemaakt in de thread van de gebruikersinterface.

De manier om dit aan te pakken, is meestal het verplaatsen van het "werk" waardoor het maken van de besturing traag verloopt op een achtergrondthread, maar maakt nog steeds het besturingselement op de UI-thread. Vervolgens gebruikt u Control.Invoke of Control.BeginInvoke om de informatie in de gebruikersinterface bij te werken zodra het langzame werk is voltooid.

Als u bijvoorbeeld een set gegevens laadt van een externe bron, kunt u het besturingselement maken en een achtergrondthread starten om de gegevens te laden. Nadat de gegevens zijn geladen, kunt u het besturingselement vervolgens bijwerken om het weer te geven. Hierdoor blijft het de hele tijd responsief.

3
toegevoegd
Helaas is dit een controle van derden met gesloten bronnen. Ik neem aan dat ik even zal kijken of het langzame deel kan worden afgescheiden.
toegevoegd de auteur fred, de bron
@fred Typisch, het is een kwestie van het instellen van de eigenschappen (dat wil zeggen: gegevens die zijn gebonden, enz.) nadat het is gemaakt in plaats van tijdens het ontwerp.
toegevoegd de auteur Reed Copsey, de bron

Het kan zijn dat uw controle niet lang duurt om te creëren; het kost veel tijd om zijn gegevens te krijgen. Overweeg in dat geval een besturingselement te maken dat de gebruikersinterface kan weergeven terwijl deze wordt gevuld. Vervolgens kunt u het besturingselement maken in uw hoofdthread, het in een thread op de achtergrond plaatsen en uw gebruikers een betere ervaring bieden.

1
toegevoegd
Helaas is dit een controle van derden met gesloten bronnen. Ik neem aan dat ik even zal kijken of het langzame deel kan worden afgescheiden.
toegevoegd de auteur fred, de bron

Gebruik achtergrondthreads om te doen wat het moet doen en meld op de een of andere manier ( bool _backgroundCompleted als een triviaal voorbeeld) dat c gereed is om te worden gemaakt.

Maak c van Timer die periodiek wordt geactiveerd en niets doet totdat _backgroundCompleted is ingesteld, maak vervolgens c aan en kill de timer.

Het is misschien 'lelijk', maar het werkt en blijft eenvoudig.

Forms.Timer, if you are asking ;)

En ja, knoeit NOOIT met meerdere threads op hetzelfde formulier. U kunt verschillende formulieren op verschillende threads gebruiken, maar daarvoor moet u eerst een nieuwe thread UITVOEREN en vervolgens een formulier ernaartoe maken. Het heeft zijn eigen berichtloop en zal het goed doen.

1
toegevoegd