2011-05-23 15 views
5

Tengo una aplicación de arquitectura S # arp que implementa un proceso ligero de procesamiento de colas mediante el cual varios subprocesos extraen entidades de una lista y establecen su estado para marcar el hecho de que el procesamiento ha comenzado en esos elementos.Problema de concurrencia de NHibernate

A pesar de incluir el bit de inicio de proceso en transacciones explícitas y el uso de un candado C#(), todavía las obtengo comenzando al mismo tiempo algunas veces.

Lamento no usar MSMQ ... bueno, sí, pero ahora este comportamiento de concurrencia me tiene desconcertado. Evidentemente, hay algo que no entiendo acerca de las transacciones y el lavado de NHibernate. ¿Me puede ayudar?

Aquí están los bits correspondientes de código:

private static object m_lock = new object(); 

private bool AbleToStartProcessing(int thingId) 
{ 
    bool able = false; 
    try 
    { 
     lock (m_lock) 
     { 
      this.thingRepository.DbContext.BeginTransaction(); 
      var thing = this.thingRepository.Get(thingId); 
      if (thing.Status == ThingStatusEnum.PreProcessing) 
      { 
       able = true; 
       thing.Status = ThingStatusEnum.Processing; 
      } 
      else 
      { 
       logger.DebugFormat("Not able to start processing {0} because status is {1}", 
         thingId, thing.Status.ToString()); 
      } 
      this.thingRepository.DbContext.CommitTransaction(); 
     } 
    } 
    catch (Exception ex) 
    { 
     this.thingRepository.DbContext.RollbackTransaction(); 
     throw ex; 
    } 
    if (able) 
     logger.DebugFormat("Starting processing of {0}", 
         thingId); 
    return able; 
} 

lo que habría esperado esto a garantizar que sólo un hilo podría cambiar el estado de una 'cosa' de una sola vez, pero conseguir esto en mis registros bastante regularmente:

2011-05-18 18:41:23,557 thread41 DEBUG src:MyApp.Blah.ThingJob - Starting processing of 78090 
2011-05-18 18:41:23,557 thread51 DEBUG src:MyApp.Blah.ThingJob - Starting processing of 78090 

.. y luego ambos hilos intentan operar en la misma cosa y crean un lío.

¿Qué me estoy perdiendo? Gracias.

edición: Código cambiado para reflejar cómo funciona mi registro en la versión real

+0

¿Pudo resolver esto? –

+0

Havent tuvo la oportunidad de probar sus sugerencias, pero lo intentaré pronto. – codeulike

Respuesta

1

instalación de concurrencia en sus asignaciones de NHibernate, este post debería ayudarle a empezar.

http://ayende.com/blog/3946/nhibernate-mapping-concurrency

+0

Guau, ¿significa esto que todo el código de transacción de Nhibernate no hace nada a menos que la opción de concurrencia esté establecida en alguna parte? – codeulike

+0

No estoy seguro, pero puede intentar esto si no desea configurar sus asignaciones. 'session.Lock (cosa, LockMode.Upgrade);' –

0

Creo que sólo se cruzan sobre el estado que está utilizando para establecer que está procesando y para comprobar que ya está procesando. primero en establecer ThingStatusEnum.Processing, pero el siguiente tipo está buscando algo diferente: ThingStatusEnum.PreProcessing. porque ThingStatusEnum.Processing! = ThingStatusEnum.PreProcessing, su bloqueo significa que dos hilos no son

+0

Pero no entiendo, incluso si hay un problema lógico en alguna parte, ¿cómo informa el registrador al mismo tiempo si está registrando desde la sección crítica? Podría ser que el registrador en sí no esté siendo preciso (Log4net?). Tal vez intente agregarse el tiempo al registro y ver si realmente colisionan, lo que parece poco probable. – Ernesto

+0

no había notado antes que los tiempos eran exactamente los mismos. tienes razón, eso indica que se está ejecutando simultáneamente. no debería ser posible con el objeto de bloqueo estático. no tiene nada que ver con la arquitectura nhibernate o s # arp. los subprocesos múltiples no deberían poder ejecutar ese código al mismo tiempo independientemente de la interacción de la base de datos. si el objeto de bloqueo no fuera estático, pensaría que está tratando con instancias diferentes, pero no tengo una respuesta para usted como es. Sigo diciendo que hay un error en el control del estado, pero no puedo explicar el tiempo en el registro. –

+0

@ Ernesto, @ Dave - uy, disculpen chicos, 'simplifiqué' el código cuando lo publiqué aquí, y moví las instrucciones de registro. En mi versión, el registro ocurre fuera de la cerradura; tiene toda la razón de que dos registros al mismo tiempo son imposibles con el código publicado. Editaré la pregunta. – codeulike

Cuestiones relacionadas