2014-09-06 2 views
-1

j'ai besoin de votre aide. Je commence juste à apprendre le sujet du filetage. Pourquoi avoir imprimé 't2' deux fois?C# Discussion données partagées

 string text = "t1"; 
     Thread t1 = new Thread (() => Console.WriteLine (text)); 
     t1.Start(); // why do not print 't1'? 
     text = "t2"; 
     Thread t2 = new Thread (() => Console.WriteLine (text)); 
     t2.Start(); // print 't2' 

Sortie:

t2 
t2 
+1

Run suffisamment de fois, et il pourrait en fait, à l'occasion –

+2

au lieu de downvoting sa question, juste fournir quelques suggestions pour lui. – RajeshKannan

Répondre

5

Parce que text est partagé ,. Le fil t1 peut démarrer (en arrière-plan) et le texte peut être assigné à t2 avant que le fil t1 puisse imprimer quoi que ce soit. Donc les deux imprimer t2. Si les choses se passaient assez vite, il pourrait parfois imprimer t1 suivi de t2.

Depuis un exemple simple a été donné, je donnerai une solution simple (mais pas trop utile):

string text = "t1"; 
Thread t1 = new Thread(() => Console.WriteLine(text)); 
t1.Start(); // why do not print 't1'? 
t1.Join(); // Wait for thread t1 to finish before continuing 

text = "t2"; 
Thread t2 = new Thread(() => Console.WriteLine(text)); 
t2.Start(); // print 't2' 

La différence est que vous attendez pour le fil t1 pour terminer l'exécution avant d'attribuer text une nouvelle valeur. Je donne seulement cet exemple comme comment vous pouvez utiliser Join pour attendre la fin d'un thread.

Une façon un peu plus complexe sans utiliser des expressions Lamda. Si vous créez une fonction statique pour faire le travail que vous pouvez passer un seul paramètre (tout type de object) à la fonction de démarrage sur le fil:

public static void DoPrint(object data) 
    { 
     Console.WriteLine((String)data); 
    } 

    static void Main(string[] args) 
    { 
     string text = "t1"; 
     Thread t1 = new Thread(DoPrint); 
     t1.Start(String.Copy(text)); // Pass a copy of text to Thread and start 

     text = "t2" 
     Thread t2 = new Thread(DoPrint); 
     t2.Start(String.Copy(text)); // Pass a copy of text to Thread and start 
    } 

Remarquez comment nous faisons une copie des données de texte avant de passer en De cette façon, même si text = "t2" se fait avant que le thread t1 ne s'imprime, cela n'aura pas d'importance car une copie a été passée. Si les deux lignes de départ avaient été:

 t1.Start(text); 
     t2.Start(text); 

alors nous aurions eu le même problème que votre exemple original pour les mêmes raisons. text est une chaîne, et les chaînes sont une classe donc elles sont passées par référence.

+0

merci. travaux. ou ajoutez ceci: 'Thread.Sleep (10);' – GUImaniac94

+1

@ GUImaniac94 Faire un sommeil ne pas « régler » le problème, il est tout simplement moins susceptible de se produire. Si vous avez besoin, vous devez mettre une sorte d'arrêt là-bas qui ne continue pas jusqu'à ce que la chose que vous attendez est fait pour passer un ordre précis des événements (c'est-ce que 'Rejoindre à()' fait). Pour comparer les deux façons, votre façon: 'Set valeur, commencer à afficher, espérons que l'affichage se termine dans les 10ms suivants, définir la valeur, commencer à afficher» Michaels façon: 'Définir la valeur, commencer à afficher, attendre pour terminer dispaying, définir valeur, commencer à afficher » –

0

car avant la t1 commence à travailler, la variable texte affecter à "t2", puis 2 et t1 commence à travailler en même temps.