2010-12-05 6 views
1

Je veux obtenir la propriété d'un certain contrôle, à partir d'un autre thread. par exemple.net multithreading winforms

string s = textBox1.Text; 

et je suis en train exception sur le threading dangereux. dans le cas où je mis la propriété, son clair pour moi, j'appelle invoquer, comme

textBox1.Invoke(new MethodInvoker..blablabla 

mais ce que je peux faire avec « get »?

+0

Voulez-vous vraiment faire cela? Se sent comme un mauvais design. – CodesInChaos

Répondre

0

Vous pouvez lire en toute sécurité les valeurs sans avoir besoin de l'appel, mais je recommanderais de ne pas le faire. Juste centraliser toutes vos lectures/écritures GUI dans le fil principal. Passez toutes les valeurs nécessaires au thread d'arrière-plan afin qu'il puisse effectuer la tâche. Ce thread d'arrière-plan ne devrait rien savoir sur l'interface graphique, il devrait obtenir une entrée, le traiter et produire un résultat qui serait transmis en utilisant la méthode Invoke afin qu'il puisse être interprété par l'interface graphique. C'est pour la réutilisation. Imaginez demain passer à une autre interface graphique comme une application console ou WPF, si votre code thread de fond est mélangé avec l'accès GUI, vous ne serez pas en mesure de facilement le réutiliser.

En outre, vous pouvez jeter un coup d'œil à BackgroundWorker qui fournit des événements pratiques pour que vous n'ayez pas besoin de marshaler manuellement les appels au thread principal avec Invoke.

+0

Ce n'est pas plus sûr juste parce que vous lisez. Dans ce cas, étant donné que les chaînes sont garanties par lecture atomique, vous pouvez les flasher, mais en général, la première ligne est un mauvais conseil. –

+0

alors, pouvez-vous me donner un exemple. Je veux obtenir du texte, à partir de textbox, dans un autre thread. Quelle est la meilleure pratique? échantillons de code s'il vous plaît, ou des liens. Je ne comprends pas, comment puis-je le concevoir – eba

+0

hm. comme passer des paramètres à l'appel asynchrone? – eba

4

Vous devez utiliser pour appeler l'obtenir aussi:

string text = null; 
someControl.Invoke((MethodInvoker) delegate { 
    text = someControl.Text; 
}); 

Discussion affinité affecte toutes les opérations; pas seulement écrit. Un autre thread pourrait être en train de changer quelque chose. Pour une chaîne, vous auriez probablement l'un ou l'autre canal (en raison de lectures de références atomiques), mais cela ne devrait pas être abusé; utilisez Invoke.

+0

Pourquoi ne pas utiliser la syntaxe lambda? '() => {text = someControl.Text; } ' – Richard

+2

@Richard - car dans ce cas, ni l'un ni l'autre n'est beaucoup plus court, et la version déléguée fonctionnera même si le lecteur utilise VS2005 –

2

Si possible, lisez la valeur de TextBox à partir du thread graphique, avant de démarrer votre thread d'arrière-plan, et envoyez cette valeur au thread d'arrière-plan en tant que paramètre.

Il est généralement souhaitable de séparer l'interface utilisateur et la logique métier, et vous pouvez bénéficier de la conception de vos tâches d'arrière-plan de telle sorte qu'elles ne connaissent aucun composant d'interface utilisateur.

Si vous devez accéder aux valeurs d'interface utilisateur à partir du thread d'arrière-plan après tout, vous pouvez toujours utiliser Invoke ou BeginInvoke pour obtenir la valeur de la zone de texte.