Segueixo pulint el tema del programa que controla el bit-rotting i la coherència de la còpia de seguretat. Tinc una tasca que triga força en executar-se i per no deixar l'interface d'usuari sense activitat (que et sorgeix el dubte... s'ha penjat o està fent algo?) aleshores millor mostrar un percentatge de progres.
El procés s'executa en un thread diferent del de l'interface d'usuari i consisteix en un bucle que executa consultes contra la BBDD. Es sap quantes consultes cal fer i dins del bucle que les fa es sap quantes en portes. Aleshores hi ha l'opció de calcular el percentatge a cada volta de bucle, però això és fer el càlcul massa sovint, també vaig fer l'opció de calcular cada "n" voltes de bucle però això depèn de si hi ha moltes consultes o poques. Aquestes dues opcions no em van agradar, jo volia que cada cert temps em digui el progres i aleshores vaig pensar en un timer. Cada n segons, 5 per exemple, que em digui que tal va.
I clar, com es posa un timer en un thread en C#? El cert és que m'ha resultat més fàcil del que hem pensava. Això de programar per que et ve degust està molt bé, perquè fas el que vols amb el temps que vols, es a dir fins que et canses. Podria haver estat un problema més difícil i tindria que haver dedicat més temps, però no, fàcil, fàcil. D'aquí poc com l'Arguiñano, rico, rico :D
Cal posar el using dels Timers, les variables globals que gestionen el càlcul del progres, la variable del Timer, inicialitzar-ho tot plegat, i fer la rutineta que fa el càlcul (UpdateProgress) i presto! Un Timer. No està de més, en catch de quan el Thread està sent abortat aturar el timer.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
namespace Dir
{
class clsBuscaRepes
{
public frmInterface Interface = null;
public decimal TantPerCentProgress = 0;
private int Progress = 0;
private int Total = 0;
private System.Timers.Timer Tmr = new System.Timers.Timer();
public void BuscaRepes()
{
try
{
clsConfig Config = new clsConfig();
string SQL = "";
DataTable TBLParaules, TBLDuplicats, TBLFitxer, TBLVerificats;
string CadConn = "";
bool UseBBDD = false;
bool Primer = true;
SqlConnection Conn = null;
string IdFitxerActual = "", IdFitxerAnterior = "";
int NumRepes = 0;
string HashActual = "";
string HashAnterior = "";
clsSQLServer SQLSvr = new clsSQLServer();
Tmr.Interval = 1000;
Tmr.Elapsed += new ElapsedEventHandler(UpdateProgress);
Config.Initialize();
UseBBDD = bool.Parse(Config.GetVal("UseBBDD"));
Interface.Log("Començant buscar fitxers repetits");
if (UseBBDD)
{
Conn = new SqlConnection();
CadConn = Config.GetVal("CadConn");
Conn.ConnectionString = CadConn;
Conn.Open();
Interface.Log("Conectat a BBDD: " + Conn.DataSource);
SQLSvr.CadConn = CadConn;
SQLSvr.Conn = Conn;
Progress = 0;
Total = 0;
SQL = "DELETE FROM ResultatsDuplicats";
SQLSvr.ExecNonQuery(SQL);
Interface.Log("Iniciant duplicats per hash");
SQL = "SELECT * FROM Fitxers WHERE Hash IN(SELECT Hash FROM fitxers "
SQL += "GROUP BY Hash HAVING ( COUNT(Hash) > 1 )) ORDER BY Hash";
TBLDuplicats = SQLSvr.Exec(SQL);
foreach (DataRow DR in TBLDuplicats.Rows)
{
HashActual = DR["Hash"].ToString();
if (HashActual == HashAnterior)
{
IdFitxerActual = DR["IdFitxer"].ToString();
SQL = "SELECT * FROM Verificats WHERE IdFitxer=" + IdFitxerAnterior + " ";
SQL += "AND IdFitxerVerificat=" + IdFitxerActual;
TBLVerificats = SQLSvr.Exec(SQL);
if (TBLVerificats.Rows.Count == 0)
{
SQL = "SELECT * FROM Fitxers WHERE IdFitxer=" + IdFitxerAnterior;
TBLFitxer = SQLSvr.Exec(SQL);
Interface.Log("Duplicat, fitxer actual: " + TBLFitxer.Rows[0]["IdFitxer"].ToString());
Interface.Log(", " + TBLFitxer.Rows[0]["Nom"].ToString());
Interface.Log("Duplicat: " + DR["IdFitxer"].ToString() + ", " + DR["Nom"].ToString());
Interface.Log("--------------------------------------------------");
SQL = "INSERT INTO ResultatsDuplicats (IdFitxer, IdFitxerPossibleDuplicat) "
SQL += "VALUES (" + IdFitxerAnterior + ", " + DR["IdFitxer"].ToString() + ");";
SQLSvr.ExecNonQuery(SQL);
NumRepes++;
}
}
else
{
HashAnterior = HashActual;
IdFitxerAnterior = DR["IdFitxer"].ToString();
}
}
SQL = "SELECT Paraula, IdFitxer FROM Paraules ORDER BY IdFitxer";
TBLParaules = SQLSvr.Exec(SQL);
SQL = "";
IdFitxerAnterior = "";
IdFitxerActual = "";
Total = TBLParaules.Rows.Count;
Tmr.Start();
foreach (DataRow Paraula in TBLParaules.Rows)
{
IdFitxerActual = Paraula["IdFitxer"].ToString();
if (IdFitxerActual == IdFitxerAnterior || Primer)
{
SQL += " AND Nom LIKE '%" + Paraula["Paraula"].ToString().Replace("'", "''") + "%'";
if (Primer)
{
Primer = false;
IdFitxerAnterior = IdFitxerActual;
}
}
else
{
SQL = "SELECT * FROM Fitxers WHERE IdCarpeta IN ";
SQL += "(SELECT IdCarpeta FROM Carpetes WHERE Duplicats=1) ";
SQL += "AND IdFitxer<>" + IdFitxerAnterior + " " + SQL;
TBLDuplicats = SQLSvr.Exec(SQL);
foreach (DataRow Duplicat in TBLDuplicats.Rows)
{
SQL = "SELECT * FROM Verificats ";
SQL += " WHERE IdFitxer=" + IdFitxerAnterior + " ";
SQL += "AND IdFitxerVerificat=" + Duplicat["IdFitxer"].ToString();
TBLVerificats = SQLSvr.Exec(SQL);
if (TBLVerificats.Rows.Count == 0)
{
SQL = "SELECT * FROM Fitxers WHERE IdFitxer=" + IdFitxerAnterior;
TBLFitxer = SQLSvr.Exec(SQL);
Interface.Log("Duplicat, fitxer actual: " + TBLFitxer.Rows[0]["IdFitxer"].ToString());
Interface.Log(", " + TBLFitxer.Rows[0]["Nom"].ToString());
Interface.Log("Duplicat: " + Duplicat["IdFitxer"].ToString() + ", " + Duplicat["Nom"].ToString());
Interface.Log("--------------------------------------------------");
SQL = "INSERT INTO ResultatsDuplicats (IdFitxer, IdFitxerPossibleDuplicat) "
SQL += " VALUES (" + IdFitxerAnterior + ", " + Duplicat["IdFitxer"].ToString() + ");";
SQLSvr.ExecNonQuery(SQL);
NumRepes++;
}
}
SQL = " AND Nom LIKE '%" + Paraula["Paraula"].ToString().Replace("'", "''") + "%'";
IdFitxerAnterior = IdFitxerActual;
}
Progress++;
}
}
Tmr.Stop();
Interface.Log("Total repetits: " + NumRepes);
Interface.BuscaRepesFinished();
}
catch (ThreadAbortException Ex)
{
if (Tmr.Enabled) Tmr.Stop();
}
catch(Exception Err)
{
Interface.Log("Error: " + Err.Message);
}
}
public void UpdateProgress(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
TantPerCentProgress = (decimal)(Progress * 100) / (decimal)Total;
Interface.Log("Processades " + TantPerCentProgress.ToString("N2") + "% de paraules");
}
catch(Exception Err)
{
}
}
}
}
|