Acessando a mesma cadeia (StringBuilder) usando multi-thread
-
13-09-2019 - |
Pergunta
O meu problema é se eu usar multi-thread na mesma corda em algum momento
a corda não vai se substituir. (Eu escrevi isso no bloco de notas de modo sintaxe pode ser
errado)
usando System.Thread ... Outros 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")
}
}
}
Agora, em algum momento algum elemento não se substituir. Assim, a minha solução para este está chamando container.Replace em um diferente
método e fazer um "bloqueio", que trabalho, mas é o caminho certo?
private class ModiflyString
{
public void Do(string x, string y)
{
lock (this)
{
fileInput.Replace(x, y);
}
}
}
Solução
Você deve bloquear o próprio objeto StringBuilder (dentro das funções substituir):
lock (container)
{
container.Replace("this", "With this");
}
ou criar um objeto de bloqueio separada:
static object _stringLock = new object();
...
lock(stringLock)
{
container.Replace("this", "With this");
}
Outras dicas
O seu bloqueio não vai funcionar quando você criar mais de 1 objeto ModifyString e eu estou supondo que você faz.
A versão simples:
public void Do(string x, string y)
{
lock (fileInput)
{
fileInput.Replace(x, y);
}
}
Pode ser melhor para criar um objeto separado para fazer o bloqueio, mas os shows acima do princípio melhor:. Todos os segmentos concorrentes deve travar no mesmo objeto
A abordagem padrão seria algo como:
private static StringBuild container = new StringBuilder();
private static object syncLock = new object(); // simple object, 1-1 with container
e então você pode (thread) usar com segurança:
lock(syncLock)
{
container.Replace(...);
}
Esta coima trabalho vontade, desde que ambas as linhas têm a mesma instância da classe ModifyString. Em outras palavras, isso vai funcionar porque a fechadura "este" deve ser um bloqueio na mesma instância:
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")
}
}
}
não trabalho, se você fez a seguir, porque bloqueio (this) não iria funcionar sentido, são duas instâncias distintas:
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")
}
}
}
Algumas pessoas realmente criar um objeto "dummy" para realizar o bloqueio em vez de usar "this" (você não pode bloquear na corda uma vez que é um tipo de valor).