C sharp - Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

   
Vista:
Imágen de perfil de Juan Carlos

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Juan Carlos (5 intervenciones) el 28/09/2017 01:42:18
Cordial saludo;


Tengo un problema con una herramienta que he diseñado con C# y necesito saber si mediante este foro encuentro una solución que me acerque a algo mas puntual.

mi programa básicamente cumple la función de hacer una base de datos con información bajada de un FTPS, la misma app tiene código para poder conectarse, descargar unos archivos rar en una carpeta que el mismo crea, luego descomprime dichos .rar los cuales contienen archivos .csv, y el path de la carpeta donde estan esta ya tomado en una variable por la app para subirlos todos a una base de datos, todo bn el programa hace todo...


luego me di cuenta que algo no estaba del todo en orden, cuando se hacia la descarga de rar o el insert de los csv en la bese de datos(phpmyadmin) la app se quedaba congelada; es normal por el loop que se hace en los for each de subir los datos.

asi que intenté usando backgroundworker para solucionar este problema, agregar una barra de carga y demas. pero esto luego trajo otro problema y es que anterior mente se tomaba un tiempo justo para subir todos los archivos pero con el backgroundworker el tiempo se multiplico por 10(como minimo)



Mis preguntas,
-se puede hacer que el backgroundworker tenga muuucha mas rapidez?,como?
-cual es la mejor alternativa para el caso que no se pueda hacer mas eficiente el backgroundworker?
-que codigo te permite limpiar memoria regularmete de la app?
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Miguel (160 intervenciones) el 28/09/2017 13:55:41
Hola,

Es normal que el código dentro de un BackgroundWorker no se ejecute tan rápido como cuando se ejecuta en el mismo proceso, ya que - repitiendo lo que comenté anteriormente - el BackgroundWorker utiliza otro hilo/proceso; lo que permite que tu aplicación (hilo principal) no se congele (generalmente en aplicaciones con UI).

Si consideras que tu código tarda demasiado o consume muchos recursos, es posible que tu código no sea óptimo o la lógica no esté bien planteada. Si colocas parte de tu código quizá podamos ayudarte...

En .NET los recursos - administrados - se liberan automáticamente cuando se considera necesario (dejan de ser referenciados/usados), aunque puedes 'forzar' un poco este proceso con el siguiente código:

1
2
3
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();


Saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Juan Carlos

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Juan Carlos (5 intervenciones) el 28/09/2017 18:30:50
Basicamente esto es lo que hace con la parte de insert en base de datos


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
 
    //conexion a base de datos para ralizar todo el proceso de volcado
    //con respectivas validaciones de autonomia
    double contin = 1;
        String glo = @"Server=" + SERV + ";Database=bd_est_airunity;UserID=" + USER + ";Password=" + PASS + "";
        MySqlConnection con = new MySqlConnection(glo); // Conexion Global
        String ins = @"Server=" + SERV + ";Database=bd_est_airunity;UserID=" + USER + ";Password=" + PASS + "";
        MySqlConnection con_aux = new MySqlConnection(ins); // Conexion auxiliar
        double count = Files_to_Upload.Length;
        //MessageBox.Show("Cuantos: " + count);
        foreach (string s in Files_to_Upload)
        {
            if (backgroundWorker1.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
 
            inter_camp = true;
            result = Path.GetFileNameWithoutExtension(s);
            string TableName = result.Split('_')[0];
 
            anti_blank = TableName.Split(' ');//SOLUCION Problema del Blanck
 
            //MessageBox.Show(anti_blank[0]);
            string TN_Val = "";
            prim = false;
            foreach (string Cad in anti_blank)
            {
                if (prim == true)
                {
                    TN_Val = TN_Val + "_" + Cad;
                }
                else
                {
                    TN_Val = Cad;
                }
 
                prim = true;
 
            }
 
            //se crearan las tablas, una por una, primero la tabla, luego los campos y el insert
            //antes de pasar a una siguiente tabla
            string query = "CREATE TABLE IF NOT EXISTS `tbl_" + TN_Val + "` (`ID` int(11) NOT NULL AUTO_INCREMENT,  PRIMARY KEY (`ID`)) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_spanish2_ci AUTO_INCREMENT=1";
            MySqlCommand cmd = new MySqlCommand(query, con);
 
            con.Open();
            cmd.ExecuteNonQuery();
            con.Close();
 
 
            this.listBox1.Items.Add("File #: " + contin + " // Table: " + TN_Val + " // Inserted into DataBase");
 
            try
            {
                using (var fs = File.OpenRead(s))
                using (var reader = new StreamReader(fs))
 
                    //se abre el while de la lectura del archivo .csv
                    while (!reader.EndOfStream)
                    {
                        var line = reader.ReadLine();
                        values = line.Split(',');
 
                        if (inter_camp == true)
                        {
                            foreach (string Col in values)
                            {
 
                                anti_blank = Col.Split(' ');//SOLUCION Problema del Blanck
                                string Col_Val = "";
                                prim = false;
                                foreach (string Cad in anti_blank)
                                {
                                    if (prim == true)
                                    {
                                        Col_Val = Col_Val + "_" + Cad;
                                    }
                                    else
                                    {
                                        Col_Val = Cad;
                                    }
 
 
                                    prim = true;
 
                                }
 
                                //MessageBox.Show(Col_Val);
 
                                // Entradas A foreach para validar Campos en la Tabla respectiva. 
                                string query_verif = "SHOW COLUMNS FROM tbl_" + TN_Val + " WHERE Field = '" + Col_Val + "'";
                                MySqlCommand cmd_verif = new MySqlCommand(query_verif, con);
                                con.Open();
                                MySqlDataReader myreader = cmd_verif.ExecuteReader();
                                if (myreader.Read())
                                {
 
                                }
                                else
                                {
 
                                    //listBox1.Items.Add("Field: " + Col_Val + "  //  into Table: " + TN_Val + "  // Will be added");
                                    //listBox1.Items.Add("//");
                                    if (Col_Val == "DateTimeStart" || Col_Val == "DateTimeEnd" || Col_Val == "DateAndTimeStart" || Col_Val == "DateAndTimeEnd")
                                    {
                                        string query_col = "ALTER TABLE `tbl_" + TN_Val + "` ADD `" + Col_Val + "` TIMESTAMP NOT NULL DEFAULT '0000-00-00'";
                                        MySqlCommand cmd_col = new MySqlCommand(query_col, con_aux);
                                        con_aux.Open();
                                        cmd_col.ExecuteNonQuery();
                                        con_aux.Close();
                                    }
                                    else
                                    {
                                        string query_col = "ALTER TABLE `tbl_" + TN_Val + "` ADD `" + Col_Val + "` VARCHAR(50) NOT NULL";
                                        MySqlCommand cmd_col = new MySqlCommand(query_col, con_aux);
                                        con_aux.Open();
                                        cmd_col.ExecuteNonQuery();
                                        con_aux.Close();
                                    }
 
                                }
 
                                con.Close();
                                inter_camp = false;
 
                            }
 
                        }
                        else
                        {
                            string ins_line = ",";
                            bool coma = false;
                            foreach (string ins_val in values)
                            {
                                if (coma == true)
                                {
                                    ins_line = ins_line + ",";
                                }
                                //MessageBox.Show(ins_val);
                                string[] anti_backslash = ins_val.Split('\\');//SOLUCION Problema del Backslash
                                if (anti_backslash[0] == "C:" || anti_backslash[0] == "D:")
                                {
                                    //MessageBox.Show("Existe el backslash");
                                    ins_line = ins_line + "'" + ins_val + "\\" + "'";
                                    //MessageBox.Show(ins_line); 
                                }
                                else
                                {
                                    //MessageBox.Show("NOO Existe el backslash");
                                    ins_line = ins_line + "'" + ins_val + "'";
                                }
 
                                coma = true;
 
                            }
 
 
                            try
                            {
                                string query_col = "INSERT INTO `tbl_" + TN_Val + "` VALUES ('null'" + ins_line + ")";
                                //MessageBox.Show("Query: " + query_col );  para saber el query
                                MySqlCommand cmd_col = new MySqlCommand(query_col, con_aux);
                                con_aux.Open();
                                cmd_col.ExecuteNonQuery();
                                con_aux.Close();
                                Thread.Sleep(50);
                            }
                            catch (MySqlException ex)
                            {
                                listBox1.Items.Add("File #: " + contin + " // Table: " + TN_Val + " // ERROR");
                                listBox1.Items.Add("---");
                                MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                con_aux.Close();
                                //throw;
                            }
 
                            //MessageBox.Show("insert Into Realizado /// Revisa la Tabla ");
                        }
                        //GC.SuppressFinalize(reader);
                    }
                listBox1.Items.Add("Success");
 
            }
            catch (Exception ex)
            {
                listBox1.Items.Add("AT File #: " + contin + " Try's ERROR");
                listBox1.Items.Add("---");
                MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
 
            //GC.SuppressFinalize(this);
            double Progreso = (contin / count) * 100;
            backgroundWorker1.ReportProgress((int)Progreso);
            listBox1.Items.Add("//");
            contin = contin + 1;
 
 
        }
 
    CheckForIllegalCrossThreadCalls = true;
 
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Yamil Bracho (1141 intervenciones) el 28/09/2017 18:42:15
Como dijo Miguel basicamente lo que estan haciendo es que tu UI no queda bloqueada por estar haciendo el proceso.
Ahora mi pregunta es si es un proceso en lotes, que quizas no necesites UI, porque no hacerlo como un servicio ? Este servicio lo puedes ejecutar a determinada hora (sin intervencion humana) y asi tendrian los usuarios su BD actualizada al llegar al siguiente dia...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Juan Carlos

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Juan Carlos (5 intervenciones) el 29/09/2017 01:52:07
pasa que la idea es trabajar con datos en tiempo real(seria lo mejor) y si esos lotes que son al rededor de 24csv; que son nuevas filas para 24 tablas en la base de datos; se generan cada 15 minutos, mas o menos con 4 dias de registros la base de datos ya va teniendo 36 millones de filas y pesando como 4gb, y ps por ser algo perfeccionista queria que la app fuera async para que se pudriera ver un reporte de si un archivo se cargo bien, y por que estado(por eso el progressbar)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Juan Carlos

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Juan Carlos (5 intervenciones) el 29/09/2017 02:43:18
igual ahora que recuerdo aun tocaria ver si se puede hacer programado ya que para poder hacer la descarga (que se hace desde un FTPS) se necesita la mano humana para poner las claves de una VPN (lo que a su vez cierra las conexiones de Internet del pc)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Miguel (160 intervenciones) el 28/09/2017 19:53:42
Ok:

1) Veo que en el código estás interactuando con controles (listBox1, MessageBox...), esto - que no sé como lo lograste directamente desde otro hilo - no ayuda a que tu código se ejecute rápidamente (al modificar los controles se fuerza a renderizar antes de continuar). Si necesariamente se debe mostrar algún estado/avance, se debería registrar en alguna variable global (a nivel Formulario puede ser) y luego verificar con un Timer si hay algún cambio a aplicar o usar el método ReportProgress, y no manipular los controles directamente como ahora.

2) Hay algunos trozos de código innecesarios que se pueden reemplazar por una sola línea, como el siguiente caso:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Por lo que veo necesitas reemplazar los espacios de una cadena por guiones bajos "_" para tener un nombre válido de tabla. 
 
// Tu código:
                    anti_blank = TableName.Split(' ');//SOLUCION Problema del Blanck
 
                    //MessageBox.Show(anti_blank[0]);
                    string TN_Val = "";
                    prim = false;
                    foreach (string Cad in anti_blank)
                    {
                        if (prim == true)
                        {
                            TN_Val = TN_Val + "_" + Cad;
                        }
                        else
                        {
                            TN_Val = Cad;
                        }
 
                        prim = true;
                    }
 
 
// Solución: usar la función string.Replace()
 
      TN_Val = TableName.Replace(' ', '_');

4) Veo que abres y cierras tus conexiones a la base de datos en cada procedimiento; no parece necesario, abre la conexión al inicio y hasta que finalice todo el proceso la cierras.

5) Hay algunas pausas en tu código (Thread.Sleep(50);), no sé que tan necesarias sean...


-------------------------------

6) Si tus archivos (CSV) no son tan pesados puedes leerlos de una sola vez, sin tener abierto el stream durante todo el proceso como ahora; usando: File.ReadAllLines()
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Juan Carlos

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Juan Carlos (5 intervenciones) el 29/09/2017 01:43:05
gracias por tus aportes, tienen un punto bueno, muy util el replace, y buscare a que se refiere el File.ReadAllLines(). tambien vi algo que puede hacer la carga mas rapido, que es practivamente en el codigo sql insertar el path de los csv pero me temo que eso podria ocacionar un ploblema si en un futuro cambian los csv, no estoy del todo seguro.

aunque aun asi, no sabria si el dejar los backgroundworker sigue afectando a la velocidad en que cargue, por eso es la importancia de las pruebas ya que esos csv que tengo que montar son generados cada 15 minutos, y no sale funcional que la herramienta tarde mas de ese tiempo en subirlos a una base de datos ya que luego no se podria trabajar en tiempo real esos datos de manera estadistica/grafica en otra herramienta web que hice.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Publicado por Miguel (160 intervenciones) el 29/09/2017 19:17:04
Claro, también es posible importar un CSV en MySQL y es bastante eficiente, ejemplo:

1
2
3
4
LOAD DATA INFILE 'archivo.csv' INTO TABLE nombre_tabla
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Wilfredo Patricio Castillo

Hacer mas rápida y eficiente tu Herramienta(Backgroundworker?)

Prueba con tareas.

Saludos cordiales,
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Revisar política de publicidad