que publicas protegidas programacion privadas poo operadores niveles modificadores modificador ejemplos delimitadores clases acceso c# thread-safety biztalk appdomain

publicas - public private protected c#



¿Cómo se usa un Dominio de aplicación para limitar el alcance de una clase estática para uso seguro de subprocesos? (6)

¿Por qué no simplemente colocar un candado alrededor del código que desea ejecutar secuencialmente? Será un cuello de botella, pero debería funcionar en un entorno multiproceso.

public class Loader { private static object SyncRoot = new object(); private string connectionString; private string fileName; private Stream stream; private DataFile dataFile; public Loader(Stream stream, string fileName, string connectionString) { this.connectionString = connectionString; this.fileName = fileName; this.stream = stream; } public void Process() { lock(SyncRoot) { dataFile = new DataFile(aredStream, fileName, connectionString); dataFile.ParseFile(); dataFile.Save(); } } }

Me ha picado una solución pobremente diseñada. ¡No es seguro para subprocesos!

Tengo varias clases y miembros compartidos en la solución, y durante el desarrollo todo fue genial ...
BizTalk ha hundido mi nave de batalla.

Estamos utilizando un adaptador de BizTalk personalizado para llamar a mis ensamblajes. El adaptador llama a mi código y ejecuta las cosas en paralelo, por lo que asumo que está usando múltiples hilos, todos bajo el mismo dominio de aplicación.

Lo que me gustaría hacer es hacer que mi código se ejecute bajo su propio Dominio de Aplicación para que los problemas compartidos que tengo no se ensucien entre sí.

Tengo una clase muy simple que el adaptador BizTalk está creando instancias y luego ejecuta un método Process ().

Me gustaría crear un nuevo AppDomain dentro de mi método Process (), de modo que cada vez que BizTalk gire otro hilo, tendrá su propia versión de las clases y métodos estáticos.

Código BizTalkAdapter:

// this is inside the BizTalkAdapter and it is calling the Loader class // private void SendMessage(IBaseMessage message, TransactionalTransmitProperties properties) { Stream strm = message.BodyPart.GetOriginalDataStream(); string connectionString = properties.ConnectionString; string msgFileName = message.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties") as string; Loader loader = new Loader(strm, msgFileName, connectionString); loader.Process(); EventLog.WriteEntry("Loader", "Successfully processed: " + msgFileName); }

Esta es la clase de llamadas de BizTalk:

public class Loader { private string connectionString; private string fileName; private Stream stream; private DataFile dataFile; public Loader(Stream stream, string fileName, string connectionString) { this.connectionString = connectionString; this.fileName = fileName; this.stream = stream; } public void Process() { //***** Create AppDomain HERE ***** // run following code entirely under that domain dataFile = new DataFile(aredStream, fileName, connectionString); dataFile.ParseFile(); dataFile.Save(); // get rid of the AppDomain here... } }

FYI: La clase Loader está en una DLL separada de la clase dataFile.

Cualquier ayuda sería apreciada. Continuaré trabajando para hacer el código Thread-Safe, pero siento que esta podría ser la respuesta "simple".

Si alguien tiene otro pensamiento, por favor inclúyalo.

Gracias,
Keith

Solo por completitud.

Encontré que si marcaba el adaptador de envío como "Entrega ordenada" en el cuadro de diálogo "Opciones avanzadas de transporte", pude evitar los problemas de múltiples hilos que estaba teniendo.

Me imagino que esta es otra posible respuesta a mi problema, pero no necesariamente a la pregunta.


¿Qué bit, exactamente, está siendo un dolor en términos de seguridad de hilo? No puedo ver ningún estado estático ni singletons, y parece que hay objetos "nuevos" apropiados ... ¿estoy siendo ciego?

Entonces, ¿cuál es el síntoma que está viendo ...

Una respuesta de AppDomain será (relativamente) lenta. Como parte de un sistema respaldado por middleware, esto podría estar bien (es decir, el "relativamente" está en el mismo parque de béisbol).

Si tiene algún estado estático en alguna parte, otra opción que a veces funciona es [ThreadStatic], que el tiempo de ejecución interpreta como "este campo estático es único por hilo". Sin embargo, debe tener cuidado con la inicialización: el constructor estático en el hilo A podría asignar un campo, pero luego el hilo B vería un nulo / 0 / etc.


Si compartió estadísticas estáticas que entran en conflicto entre sí, entonces puede intentar agregar el atributo [ThreadStatic]. Esto los hará locales para cada hilo. Eso puede resolver su problema a corto plazo. Una solución correcta sería simplemente rearchitect sus cosas para ser seguro para subprocesos.


Usando dominios de aplicaciones puedes hacer algo como esto:

public class Loader { private string connectionString; private string fileName; private Stream stream; private DataFile dataFile; public Loader(Stream stream, string fileName, string connectionString) { this.connectionString = connectionString; this.fileName = fileName; this.stream = stream; } public void Process() { //***** Create AppDomain HERE ***** string threadID = Thread.CurrentThread.ManagedThreadId.ToString(); AppDomain appDomain = AppDomain.CreateDomain(threadID); DataFile dataFile = (DataFile) appDomain.CreateInstanceAndUnwrap( "<DataFile AssemblyName>", "DataFile", true, BindingFlags.Default, null, new object[] { aredstream, filename, connectionString }, null, null, null); dataFile.ParseFile(); dataFile.Save(); appDomain.Unload(threadID); } }


Solo por completitud.

Encontré que si marcaba el adaptador de envío como "Entrega ordenada" en el cuadro de diálogo "Opciones avanzadas de transporte", pude evitar los problemas de múltiples hilos que estaba teniendo.

Me imagino que esta es otra posible respuesta a mi problema, pero no necesariamente a la pregunta.


Crear y derribar un dominio de aplicación para cada llamada, supongo que no te preocupa el rendimiento en esta.

Idealmente, debería cambiar el código llamado para que sea seguro.