teclas - habilitar y deshabilitar botones en c#
¿Cómo bloquear varios objetos? (8)
Quiero bloquear dos objetos al mismo tiempo. ¿Por qué no puedo escribir como ese código?
bloqueo (obj1, obj2)
¿Debo siempre escribir así?
lock (obj1)
{
lock (obj2)
{
}
}
Probablemente esto podría ser más simple? Probablemente sería mejor introducir un objeto privado especial y usarlo para un bloqueo ...
Bueno, esta pregunta es demasiado antigua pero, aquí hay una compacta que descubrí, ambos códigos terminarán en las mismas declaraciones compiladas (esta y la de la descripción de la pregunta):
lock (obj1) lock (obj2)
{
// your code
}
El bloqueo aquí no significa que durante la duración del bloqueo ningún otro código de otro hilo pueda acceder o modificar el objeto. Si bloquea un objeto, cualquier otro hilo puede modificar el objeto al mismo tiempo. Lo que el bloque de código de bloqueo le permite hacer es hacer que el código dentro del bloque de bloqueo sea una sola entrada, es decir, solo un hilo puede ejecutar el bloque de código de bloqueo una vez y los otros hilos que intenten ejecutar el mismo bloque de código tendrán que esperar hasta que el propietario hilo se realiza con la ejecución del bloque de código. Básicamente, no es necesario bloquear 2 o más objetos en los casos habituales. Al bloquear su propósito es hacer que el bloque de código ingrese una sola entrada.
En lugar de bloquear los objetos en sí mismos, crea un objeto dedicado llamado PadLock o similar y solo lo bloquea cuando sea necesario.
Esa es la forma correcta de bloquear en múltiples objetos, sí.
Mi conjetura es que la razón para solo permitir un solo argumento a la declaración de bloqueo es hacer que el orden en que se toman los bloqueos sea lo más claro posible.
Tenga en cuenta que debe asegurarse de que los dos bloqueos se tomen en el mismo orden en todas partes de su código, o tiene un potencial de interbloqueo.
También podría, como sugiere, introducir un único objeto de bloqueo dedicado, pero eso haría que su bloqueo sea más burdo. Todo depende de tus necesidades. Si a veces solo necesita uno de los bloqueos, debe mantenerlos separados (pero asegúrese de conservar el orden de bloqueo, como se mencionó anteriormente).
Hacer algo como
internal static void DuoEnter(object po1, object po2, int pnTimeOutMs = 1000)
{
if ((po1 == null) && (po2 == null))
return;
int nMaxLoops = 100 * pnTimeOutMs;
bool lOneProcessor = Environment.ProcessorCount < 2;
for (int nLoops = 0; nLoops < nMaxLoops; nLoops++)
{
if ((po1 == null) || (po2 == null) || (po1 == po2))
{
if (Monitor.TryEnter(po1 ?? po2))
return;
}
else
{
if (Monitor.TryEnter(po1))
if (Monitor.TryEnter(po2))
return;
else
Monitor.Exit(po1);
}
if (lOneProcessor || (nLoops % 100) == 99)
Thread.Sleep(1); // Never use Thread.Sleep(0)
else
Thread.SpinWait(20);
}
throw new TimeoutException(
"Waited more than 1000 mS trying to obtain locks on po1 and po2");
}
internal static void DuoExit(object po1, object po2)
{
if ((po1 == null) && (po2 == null))
return;
if (po1 == null || po2 == null || po1 == po2)
Monitor.Exit(po2 ?? po1);
else
{
Monitor.Exit(po2);
Monitor.Exit(po1);
}
}
La razón por la que tiene que hacerlo como lo escribió, es porque no puede bloquear dos objetos al mismo tiempo; Ciérralos uno tras otro (y es muy importante mantener el orden del bloqueo, de lo contrario, podría llegar a un punto muerto), y es mejor ser lo más explícito posible con estas cosas.
Me he encontrado con el mismo tipo de problema y escribí este fragmento de código que podría ayudarte, aunque está lejos de ser perfecto:
private void MultiLock(object[] locks, WaitCallback pFunc, int index = 0)
{
if (index < locks.Count())
{
lock (locks[index])
{
MultiLock(locks, pFunc, index + 1);
}
}
else
{
ThreadPool.QueueUserWorkItem(pFunc);
}
}
Y luego, simplemente llame a este método como este:
public object LockedObject1 = new Object();
public object LockedObject2 = new Object();
public void MyFunction(object arg)
{
WaitCallback pFunc = delegate
{
// Operations on locked objects
}
MultiLock(new object[] {LockedObject1, LockedObject2}, pFunc);
}
Si escribe un código como este, debe asegurarse de que siempre bloquee esos dos objetos en este orden. De lo contrario, podría encontrarse con puntos muertos.