Diskuze: použití System.Timers.Timer
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 10 zpráv z 10.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
ještě jsem zapomněl dodat metodu TryDbAgain(), která jenom opět zavolá LoadSetting, je to takto správně?
private void TryDbAgain(object sender, EventArgs e)
{
LoadSettings();
}
obavam se ze to fungovat nebude. poradi provadeni je try-catch-finally to znamena ze v try si udelas timer, v catch na vyjimce ho spustis a hned na to ho ve finally zrusis takze se nikdy neprovede.
dalsi nedostatky bych videl v nepouzivani bloku using pro connection, command a datareader. taky je problem v poradi timer.start a timer.elapsed. v tomhle konkretnim pripade to bude fungovat ale v pripade mensiho casu uz to nemusi nutne fungovat. a taky timer.enable=true je to same jak timer.start
Díky za komentář
ale asi to je tedy špatně, myslíš, že by jsi mně mohl prosím naznačit lepší cestu?
Předem děkuji
jo a taky sem zapomel ze to tvoje vubec nebude fungovat pres ten casovac protoze ty na casovaci volas TryDbAgain ktera vola LoadSettings ktera ti vraci ty settings. Ale pri volani z toho casovace nic nedelas s tema hodnotama. Taky je dobre si uvedomit, ze zrovna tenhle casovac neni UI, takze v obsluze toho casovace nemuzes manipulovat s UI prvky (nemuzes nic delas s labelama,tlacitkama atd.). Ja osobne bych pouzil tuhle konstrukci
private void StartMethod()
{
Retry(() =>
{
//co je v tomhle bloku se provede na jinem vlakne
var data = GetDataFromDB();
label1.Invoke(new Action(() => label1.Text = data.ToString())); //co je volane v invoke to se provede na UI vlakne
}, 5, TimeSpan.FromSeconds(1));
}
public object GetDataFromDB()
{
//zde je originalni kod pro nacteni dat
return null;
}
private void Retry(Action what, int retryCount, TimeSpan delay)
{
Task.Factory.StartNew(() => //vytvori nove vlakno
{
for (int i = 0; i < retryCount; i++)
{
try
{
what(); //na tom novem vlakne skusi provest originalni akci
return;
}
catch (Exception ex)
{
Thread.Sleep(delay); //kdyz se ta originalni akce nepovede uspi se to a zkusi znova doku jede hlavní cyklus
}
}
});
}
snazil sem se najit balanc mezi jednoduchou implementaci a pouzitelnosti.
tyjo, tak to je už na mě moc brutální ať na to koukám, jak koukám, tak
to stjně tak nějak nemá hlavu a patu
UI nepotřebuji, protože se snažím vytvořit službu, která
poběží na pozadí systému, která UI stejně nemá
myslíš, že by jsi mně pomohl ten
timer napasovat na ten kód co mám, aby mně to dávalo alespoň trochu
smysl??? V C# se po kouskách pousunuju dopředu a dopředu, ale toto je na mě
až moc velká dávka
Udělal bych to takto, radši než přes úlohy přes vlákna, podporují
starší framework , je to
podobné timeru, jen lepší
private void nacteni_nastaveni()
{
string pc_name = System.Environment.MachineName;
string sql = "SELECT pc_name, account, lop_prg_path, lop_detect_path, lop_param, sam_prg_path, sam_detect_path, active, last_detect, period_scan, update_interval FROM oez.ScanSettings WHERE pc_name=@pc_name";
SqlConnection con = new SqlConnection(_connection);
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader row;
Setting set = new Setting();
try
{
cmd.Parameters.AddWithValue("@pc_name", pc_name);
con.Open();
row = cmd.ExecuteReader();
while (row.Read())
{
set.pc_name = row["pc_name"].ToString();
set.account = row["account"].ToString();
set.lop_prg_path = row["lop_prg_path"].ToString();
set.lop_detect_path = row["lop_detect_path"].ToString();
set.lop_param = row["lop_param"].ToString();
set.sam_prg_path = row["sam_prg_path"].ToString();
set.sam_detect_path = row["sam_detect_path"].ToString();
set.active = row.GetInt32(row.GetOrdinal("active"));
set.last_detect = row.GetDateTime(row.GetOrdinal("last_detect"));
set.period_scan = row.GetInt32(row.GetOrdinal("period_scan"));
set.update_interval = row.GetInt32(row.GetOrdinal("update_interval"));
}
}
catch (Exception ex)
{
neslo_se_pripojit();
}
}
private bool zkouska_pripojeni()
{
try
{
//zde se pokusis pripojit
return true;
}
catch
{
return false;
}
}
private void neslo_se_pripojit()
{
Thread t = new Thread(timer);
t.Start();
}
private void timer()
{
bool p = true;
while (p)
{
p = zkouska_pripojeni();
Thread.Sleep(500);
}
}
Pokud by ta aplikace nedělala v tu chvíli nic jiného, tak stačí vlákno
uspat a timer ani nic jiného nemusíš vůbec řešit .
ok. snazil sem se to trochu osekat.
private void StartMethod()
{
//tady se neco deje predtim nez chces zavolat tu metodu
string result = Retry(GetDataFromDB, 5, TimeSpan.FromSeconds(1)) as string;
//tady zpracujes ten vysledek
}
public string GetDataFromDB()
{
//zde je originalni kod pro nacteni dat
return null;
}
private object Retry(Func<object> what, int retryCount, TimeSpan delay)
{
for (int i = 0; i < retryCount; i++)
{
try
{
return what();
}
catch (Exception ex)
{
Thread.Sleep(delay); //kdyz se ta originalni akce nepovede uspi se to a zkusi znova doku jede hlavní cyklus
}
}
return null; //budto vrati null kdyz vyprsi pokusy a nepodari se ziskat data
// nebo throw new Exception(); abys to zhavaroval
}
To nestačí něco takhle jednoduchého?
new Thread(() =>
{
while (true)
{
var data = GetDataFromDB();
if (data == null)
Thread.Sleep(TimeSpan.FromMinutes(1));
else
break;
}
}).Start();
nebo jestli tam vyhazuješ vyjímku
new Thread(() =>
{
bool success = false;
do
{
try
{
var data = GetDataFromDB();
success = true;
}
catch (Exception ex)
{
Thread.Sleep(TimeSpan.FromMinutes(1));
}
} while (!success);
}).Start();
Zobrazeno 10 zpráv z 10.