| |||
Error Hashtable Buenas , estoy trabajando con hashtables con c#, la dinamica es la siguiente leer de un archivo, extraer informacion del mismo e ir guardandola en una hashtable, el problema es que en cierto punto me da un error de Out Of Memory Exception, por lo que sospecho que el hashtable no tiene capacidad de almacenar mas datos, como podria solventar este problema les agradezco mucho su colaboracion. |
| |||
Respuesta: Error Hashtable El codigo es este public List<Hashtable> leerCargaTxt(configuracion estrucTablas) { Singleton.Instance.progreso.PerformStep(); Singleton.Instance.resultados.Items.Add(DateTime.N ow + ": Lectura del Archivo de Carga " + estrucTablas.nombArchOrigen.ToString()); int numeroColumnas = estrucTablas.tipoAtr.Count; //Numero de columnas que hay en el archivo config List<Hashtable> columnas = new List<Hashtable>(); for (int i = 0; i < numeroColumnas; i++) //Aqui se agregan el numero de HashTables que hay dentro de cada tabla (una por atributo) { columnas.Add(new Hashtable()); } try { //Lectura de archivo de data StreamReader lectCarga = new StreamReader(Singleton.Instance.rutaDataFuente.Tex t + "\\" + estrucTablas.nombArchOrigen); string Linea = ""; int fila = 0;//Filas que se van recorriendo del archivo de lectura Linea = lectCarga.ReadLine(); while (Linea != null)//Aqui se lee linea a linea el archivo donde viene la data para ser guardado en el vector lineas { //Creacion de Lista de Hashtables en el orden especificado con Will string[] atributos = Linea.Split('|'); for (int columna = 0; columna < atributos.Length; columna++) { try { //valida el numero de columnas corresponda con el numero de atributos if (atributos.Length > numeroColumnas) throw new ExceptionNumeroColumnas(fila, estrucTablas.nombArchOrigen.ToString()); //valida el largo de cada atributo corresponda con el largo de la configuracion if (atributos[columna].Length > Convert.ToInt32(estrucTablas.tipoAtr[columna].tamano)) throw new ExceptionLongCampos(fila, columna, estrucTablas.nombArchOrigen.ToString()); //valida el tipo de dato bool tipo = validaTipo(atributos[columna], estrucTablas.tipoAtr[columna].tipoAtr); if (tipo == false) throw new ExceptionTipoAtributo(fila, columna, estrucTablas.nombArchOrigen.ToString()); else//Aqui se agregan las filas { if (columnas[columna].Contains(atributos[columna]))//Aqui se agrega la fila en la que se encuentra ese registro esto si el atributo ya esta cargado en el hash { List<int> posiciones = (List<int>)columnas[columna][atributos[columna]]; posiciones.Add(fila); columnas[columna][atributos[columna]] = posiciones; } else//Aqui se agrega la fila en la que se encuentra ese registro y el valor del registro como tal esto si el atributo NO esta cargado en el hash { List<int> posiciones = new List<int>(); posiciones.Add(fila); columnas[columna].Add(atributos[columna], posiciones); } } } catch (ExceptionLongCampos ex) { ControlInterfaz.log.Add(DateTime.Now + " : " + ex); Singleton.Instance.resultados.Items.Add(" ERROR: por tanto NO se ha podido cargar el archivo " + estrucTablas.nombArchOrigen.ToString()); return null; } catch (ExceptionTipoAtributo ex) { ControlInterfaz.log.Add(DateTime.Now + " : " + ex); Singleton.Instance.resultados.Items.Add(" ERROR: por tanto NO se ha podido cargar el archivo " + estrucTablas.nombArchOrigen.ToString()); return null; } catch (ExceptionNumeroColumnas ex) { ControlInterfaz.log.Add(DateTime.Now + " : " + ex); Singleton.Instance.resultados.Items.Add(" ERROR: por tanto NO se ha podido cargar el archivo " + estrucTablas.nombArchOrigen.ToString()); return null; } } fila++; Linea = lectCarga.ReadLine(); } estrucTablas.numRegis = fila; lectCarga.Close(); } catch (FileNotFoundException ex) { ControlInterfaz.log.Add(DateTime.Now + " : " + ex); Singleton.Instance.resultados.Items.Add("ERROR : El archivo " + estrucTablas.nombArchOrigen.ToString() + " NO se pudo encontrar"); return null; } return columnas; } Aqui es donde leo el archivo y lo vacio dentro de cada hashtable incluida en el vector de columnas |
| |||
Respuesta: Error Hashtable Pero estas seguro de que no me esta dando el error pq la hashtable llega al maximo de su capacidad? y te digo esto pq estoy trabajando en servidor de 12 GB de RAM |
| |||
Respuesta: Error Hashtable Hice lo que me indicaste con los vectores y lleno la tabla de hash con 15 millones de Keys pero ahora cuando voy a escribir dentro de este metodo public void Escribir(FileStream archivo, Hashtable tabla) { try { Singleton.Instance.progreso.PerformStep(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(archivo, tabla); } finally { archivo.Close(); } } Me da el error de Out Of memory Exception, y cuando me coloco sobre la Hastable "Tabla" en vez de mostrarme los valores que tiene la hashtable dice " Function Evaluation disabled because a precious function evaluation timeout You must continue execution to reenable function execution" |
| ||||
Respuesta: Error Hashtable ok entonces es a la escritura , el detalle aqui q puede suceder es q al momento de serializar tu clase tabla este no tenga el atributo de serializable o uno de tus atributos dentro de tu clase q estas serializando (una propiedad) esta en un ciclo sin fin y provoca la excepcion. puede sponer el codigo de tus clases q van dentro de tu hashtable q tienes con el atributo "serializable" |
| |||
Respuesta: Error Hashtable Nuevamente muchas Gracias por tu Ayuda Peter muy amable como siempre, la cuestion es la siguiente yo serializo una hashtable para almacenarla de forma binaria dentro de un archivo de texto, tengo ya meses haciendolo el problema me surgio ahora cuando trate trabajar con un archivo de 15 millones de lineas como archivo fuente es decir la tabla de hash ahorita tendra 15 millones de keys diferentes. public void Escribir(FileStream archivo, Hashtable tabla) { try { Singleton.Instance.progreso.PerformStep(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(archivo, tabla); } finally { archivo.Close(); } } como te mencionaba anteriormente a este metodo llegan el nombre de un filestream donde se almacenara la tabla de forma binaria y la tabla de hash como tal. La linea de BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(archivo, tabla); Deriva de la clase System.Runtime.Serialization.Formatters.Binary; No entiendo entonces que puede estar ocurriendo |
| ||||
Respuesta: Error Hashtable donde esta la linea donde estas invocando a este metodo la linea exacta. debes tener una linea clase.Escribir(obj.archivom,obj.tabla) si es asi pon entonces las lineas donde defines obj.tabla (la propiedad) |
| |||
Respuesta: Error Hashtable El codigo completo es el siguiente Peter public void Escribir(FileStream archivo, Hashtable tabla) { try { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(archivo, tabla); } finally { archivo.Close(); } } public void EscrituraCarg(List<Hashtable> columnas, configuracion estrucTablas, int numTablas) { for (int descar = 0; descar < columnas.Count; descar++) { FileStream archColumn = new FileStream(Singleton.Instance.rutaUbicacionData.Te xt + "\\" + estrucTablas.tipoAtr[descar].nombAtr + "_" + estrucTablas.nombTab + ".txt", FileMode.Create, FileAccess.Write); Escribir(archColumn, columnas[descar]); } } class configuracion { String nombTabla; String nombArchivoOrigen; String tipoArchivo; String hojaExcel; int numRegistros; List<tipoAtrib> tipoAtrib = new List<tipoAtrib>(); public string nombTab { get { return nombTabla; } set { nombTabla = value; } } public string nombArchOrigen { get { return nombArchivoOrigen; } set { nombArchivoOrigen = value; } } public string tipoArch { get { return tipoArchivo; } set { tipoArchivo = value; } } public List<tipoAtrib> tipoAtr { get { return tipoAtrib; } set { tipoAtrib = value; } } public string hojaExc { get { return hojaExcel; } set { hojaExcel = value; } } public int numRegis { get { return numRegistros; } set { numRegistros = value; } } En la linea public void EscrituraCarg(List<Hashtable> columnas, configuracion estrucTablas, int numTablas) columnas es una lista de hashtables , configuracion es una estructura que contiene lo que te coloque debajo de ese metodo EscrituraCarg int numTablas es un entero cualquiera. |
| ||||
Respuesta: Error Hashtable ok ya da un poco mas de panoramo ahora la linea donde invocas a EscrituraCarg(List<Hashtable> columnas, configuracion estrucTablas, int numTablas) |
| |||
Respuesta: Error Hashtable Esto es parte de una clase Factory que implemento public void DoIt(List<Hashtable> colum, Escritura escribir, Lectura leer, configuracion estructura, int numTablas) { colum = leer.leerCargaTxt(estructura); if (colum != null) escribir.EscrituraCarg(colum, estructura, numTablas); } y leerCargaTxt es el metodo que te puse al principio del hilo |
| ||||
Respuesta: Error Hashtable ok esta perfecto pero esto casi seguro q una de las invocaciones de esa list<hashtable> esta haciendo un loop sin fin en el get mas q en el set. una vez mas la linea donde estas invocando a ese DoIt(obj.column,.....) |
| |||
Respuesta: Error Hashtable Esta es la clase Factory class Factory { public Base GetObject(string tipoArch) { Base tipoProc = null; switch (tipoArch) { case "Excel": tipoProc = new archExcel(); break; case "Fijo": tipoProc = new archFijo(); break; case "Delimitado": tipoProc = new archDelimitado(); break; } return tipoProc; } } interface Base { void DoIt(List<Hashtable> colum, Escritura escribir, Lectura leer, configuracion estructura, int numTablas); } class archExcel : Base { public void DoIt(List<Hashtable> colum, Escritura escribir, Lectura leer, configuracion estructura, int numTablas) { colum = leer.leerCargaExcel(estructura, estructura.hojaExc); if (colum != null) escribir.EscrituraCarg(colum, estructura, numTablas); } } class archFijo : Base { public void DoIt(List<Hashtable> colum, Escritura escribir, Lectura leer, configuracion estructura, int numTablas) { int[] anchos = leer.LeerConfigAnchos(estructura); colum = leer.leerCargaAnchoFijo(estructura, anchos); if (colum != null) escribir.EscrituraCarg(colum, estructura, numTablas); } } class archDelimitado : Base { public void DoIt(List<Hashtable> colum, Escritura escribir, Lectura leer, configuracion estructura, int numTablas) { colum = leer.leerCargaTxt(estructura); if (colum != null) escribir.EscrituraCarg(colum, estructura, numTablas); } } Y este es el metodo ue comienza toda la ejecucion de la carga public void EjecutarCarga() { try { Lectura leer = new Lectura(); List<configuracion> estructura = leer.leerConfig(Singleton.Instance.RutaArchConfigu racion.Text);//Lee la configuracion inicial de tablas y atributos if (estructura == null) throw new ExceptionFinEjecucion();//Tira una excepcion si hubo problemas con el archivo de estructura Escritura escribir = new Escritura(); for (int numTablas = 0; numTablas < estructura.Count; numTablas++) { List<Hashtable> colum = new List<Hashtable>();//Lista de Hashtables donde van las columnas de cada tabla Factory factory = new Factory();//Decide a que tipo de archivo ir Base obj = factory.GetObject(estructura[numTablas].tipoArch); obj.DoIt(colum, escribir, leer, estructura[numTablas], numTablas);//Va a la ejecucion de ese tipo de archivo } escribir.EscrituraDiccio(estructura); } catch (ExceptionFinEjecucion ex) { log.Add(DateTime.Now + " : " + ex); } Singleton.Instance.resultados.Items.Add(DateTime.N ow + ": Fin de la ejecucion "); Singleton.Instance.progreso.Value = 100; } Desde aqui llamas al DoIt de la clase factory segun sea elc aso del archivo que estes leyendo (Excel,delimitado,Ancho fijo) |
| ||||
Respuesta: Error Hashtable ok retomando lo anterior todavia podemos hacer unas cuantas optimizaciones al codigo para evitar tener problemas de exceso de memoria. public void EscrituraCarg(List<Hashtable> columnas, configuracion estrucTablas, int numTablas) { for (int descar = 0; descar < columnas.Count; descar++) { FileStream archColumn = new FileStream(Singleton.Instance.rutaUbicacionData.Te xt + "\\" + estrucTablas.tipoAtr[descar].nombAtr + "_" + estrucTablas.nombTab + ".txt", FileMode.Create, FileAccess.Write); Escribir(archColumn, columnas[descar]); archColumn.Close(); // liberamos ese stream y no dentro del escribir } porque hacer esto, garantizar q al estar en el mismo ambito no se ocupe mas tiempo y memoria. digo sigo revisando q podria ser pero hagamos algunos cambios para poder optimizar tiempo y memoria } |
| |||
Respuesta: Error Hashtable No existe un manera de liberar memoria antes de pasar a la serializacion, ya prove con garbageCollector pero no me funcion quizas no lo utilize bien que opinas. |
| |||
Respuesta: Error Hashtable Inclusive Peter estoy chequeando y el archivo Binario se esta creando solo que de forma incompleta pq me imagino que se corta su creacion cuando da el out of memory exception y lo deja escrito de manera incompleta |
| ||||
Respuesta: Error Hashtable si es eso abria q checar si te conviene usar referencias es decir Escribir (ref list<hashtables>,....) y asi reducir tambien un poco la memoria usada solo pasando la referencia de esa coleccion |
| ||||
Respuesta: Error Hashtable si cuando haces Escribir(list<hashtable> ... en vez de crear un nuevo espacio para el list hashtable lo q haces es pasar la referencia al objeto de la invocacion algo asi como usar & en c++ |
| |||
Respuesta: Error Hashtable Peter disculpa que no te respondiera antes pero estuve haciendo un poco de investigacion , para poder darte un poco mas de luces en el problema, el error es este http://www.codeproject.com/KB/cs/Lar...__Trouble.aspx Aqui nos hablan de LOH (Large Object Heap) , lo que entiendo es que los objetos de estilo Hashtable (LOH) reservan en memoria un Heap de memoria y cuando lo llenan obtenemos el error de OutOfMemory Exception yo aplique este pedazo del codigo Catch(OutOfMemory Exception) { } Finally { array = null; GC.Collect(); GC.WaitForPendingFinalizers(); } Con esto logre que no se cayera la aplicacion y me escribiera el archivo con la tabla de hash, ahora tenemos 2 problemas cuando lo trato de leer me da un error y dice que no puede terminar de deszerializar , no obstante ese no es el mas grave sino que inclusive con las modificacion el archivo no se esta guardando completo Que opinas... |
| ||||
Respuesta: Error Hashtable sabes q estuve pensando hacer que fueces escribiendo cada hashtable y eliminandola despues de escribir asi garantizas q tienes espacio disponible despues de la primera escritura |
| |||
Respuesta: Error Hashtable El problema Peter es que en el caso que estoy ahorita estoy escribiendo 1 sola tabla de hash y a la primera cae en el out of memory como te dije ya lo controlo pero no me escribe la tabla completa dentro del hash. |