2009-08-12 4 views
0

Mon problème est si j'utilise multi-thread sur la même chaîne parfoisAccès à la même chaîne (StringBuilder) à l'aide multi-thread

la chaîne ne sera pas remplacer. (Je l'ai écrit ceci sur le bloc-notes si la syntaxe peut être

mal)

utilisant System.Thread ... D'autres ofcourse

class .... 
{ 
    private static StringBuild container = new StringBuilder(); 

    static void Main(...) 
    { 
    container.Append(Read From File(Kind of long)); 
    Thread thread1 = new Thread(Function1); 
     Thread thread2 = new Thread(Function2); 
    thread1.Start(); 
    thread2.Start(); 
    //Print out container 
    } 

    static void Function1 
    { 
    //Do calculation and stuff to get the Array for the foreach 
    foreach (.......Long loop........) 
    { 
    container.Replace("this", "With this") 
    } 
    } 
    //Same goes for function but replacing different things. 
    static void Function2 
    { 
    //Do calculation and stuff to get the Array for the foreach 
    foreach (.......Long loop........) 
    { 
    container.Replace("this", "With this") 
    } 
    } 
} 

maintenant quelque temps un élément ne soit pas remplacé. Donc, ma solution à cela appelle conteneur.Remplacer sur une autre méthode et faire un "verrou" qui fonctionne mais est-ce la bonne façon?

private class ModiflyString 
{ 
     public void Do(string x, string y) 
      { 
       lock (this) 
       { 
        fileInput.Replace(x, y); 
       } 
      } 
} 

Répondre

5

Vous devez verrouiller l'objet StringBuilder lui-même (dans le remplacement des fonctions):

lock (container) 
{ 
    container.Replace("this", "With this"); 
} 

ou créer un objet de verrouillage séparé:

static object _stringLock = new object(); 

... 

lock(stringLock) 
{ 
    container.Replace("this", "With this"); 
} 
+0

Je n'ai jamais pensé à verrouiller le stringbuilder lui-même, très sympa. merci, –

+0

Le deuxième exemple de Phil est ce dont je parle quand j'ai mentionné un objet "factice". Cependant, je pense que son premier exemple où il verrouille le conteneur est le meilleur de tous.Étant donné que le conteneur représente les données partagées entre les threads, vous souhaitez verrouiller cela. Si vous avez utilisé mon exemple, le problème est que si vous aviez des threads qui essayaient d'appeler ModifyString.Do pour des conteneurs totalement séparés, ils se bloqueraient les uns les autres, même si les conteneurs avec lesquels ils travaillent sont totalement différents. Donc, vous blesseriez la performance. Donc, mon exemple est vraiment une mauvaise implémentation. – AaronLS

+0

merci @arronls maintenant mon programme fonctionne :) –

3

Votre verrouillage ne fonctionnera pas lorsque vous créez plus d'un objet ModifyString et je suppose que vous le faites.

Une version simple:

public void Do(string x, string y) 
    { 
     lock (fileInput) 
     { 
     fileInput.Replace(x, y); 
     } 
    } 

Il peut être préférable de créer un objet distinct pour faire le verrouillage, mais le montre au-dessus du principe mieux: toutes les discussions concurrentes doivent se verrouiller sur le même objet.

Une approche standard ressemblerait à ceci:

private static StringBuild container = new StringBuilder(); 
private static object syncLock = new object(); // simple object, 1-1 with container 

et vous pouvez (thread-) utiliser en toute sécurité:

lock(syncLock) 
    { 
     container.Replace(...); 
    } 
+0

J'ai créé un objet, c'est pourquoi je peux utiliser "this" –

+0

Mais as-tu instancié _only_ 1? C'est le but. –

+1

Non, vous avez créé _many_ objects - chaque instance de ModifyString est son propre objet. –

2

Cela fonctionnera correctement tant que les deux threads ont la même instance de la classe ModifyString. En d'autres termes, cela fonctionne parce que le verrou sur « ce » doit être un verrou sur la même instance:

class Blah 
{ 
    private static StringBuild container = new StringBuilder(); 

    private static ModifyString modifyString = new ModifyString(); 

    static void Main(...) 
    { 
    container.Append(Read From File(Kind of long)); 
    Thread thread1 = new Thread(Function1); 
     Thread thread2 = new Thread(Function2); 
    thread1.Start(); 
    thread2.Start(); 
    //Print out container 
    } 

    static void Function1 
    {  

     //Do calculation and stuff to get the Array for the foreach 
     foreach (.......Long loop........) 
     { 
      modifyString.Do("this", "With this") 
     } 
    } 
    //Same goes for function but replacing different things. 
    static void Function2 
    { 
     //Do calculation and stuff to get the Array for the foreach 
     foreach (.......Long loop........) 
     { 
      modifyString.Do("this", "With this") 
     } 
    } 
} 

Il PAS travail si vous avez fait le ci-dessous, parce que verrou (cela) ne fonctionnerait pas sens, ils sont deux cas distincts:

class Blah 
{ 
    private static StringBuild container = new StringBuilder(); 

    static void Main(...) 
    { 
    container.Append(Read From File(Kind of long)); 
    Thread thread1 = new Thread(Function1); 
     Thread thread2 = new Thread(Function2); 
    thread1.Start(); 
    thread2.Start(); 
    //Print out container 
    } 

    static void Function1 
    { 
     ModifyString modifyString = new ModifyString(); 
     //Do calculation and stuff to get the Array for the foreach 
     foreach (.......Long loop........) 
     { 
      modifyString.Do("this", "With this") 
     } 
    } 
    //Same goes for function but replacing different things. 
    static void Function2 
    { 
     ModifyString modifyString = new ModifyString(); 

     //Do calculation and stuff to get the Array for the foreach 
     foreach (.......Long loop........) 
     { 
      modifyString.Do("this", "With this") 
     } 
    } 
} 

Certaines personnes effectivement créer un objet « factice » pour effectuer la serrure au lieu d'utiliser « ce » (vous ne pouvez pas verrouiller sur la corde, car il est un type de valeur).

+0

StringBuilder n'est pas un type de valeur que vous connaissez ce droit? –

+0

Je n'ai pas dit stringbuiler, j'ai dit string. – AaronLS