(C#.NET) - Jak przyspieszyć wykonanie tego kodu i rozwiązać problem z zacinaniem się?

(1niez) #1

Cześć wszystkim!

Tak jak w temacie wspomniałem chciałbym przyspieszyć wykonywanie tego kodu:

 cts = new CancellationTokenSource();
                CancellationToken token = cts.Token;
                Task.Factory.StartNew(() =>
                {
                    token.ThrowIfCancellationRequested();
                    foreach (var obj in listBox1.Items)
                    {
                        string dir = Convert.ToString(obj);
                        listBox3.DataSource = GetFileList("*.*", dir).ToArray();
                        int count = listBox3.Items.Count;
                        for (int i = 0; i < count; i++)
                        {
                            listBox5.Items.Add(listBox3.Items[i].ToString());
                        }
                    }
                    string filecount = Convert.ToString(listBox5.Items.Count);
                    textBox1.Text = filecount;
                    ExecuteSecure(() => label2.Text = "Sprawdzono: 0 z " + filecount);


                    ExecuteSecure(() => label5.Visible = false);
                    ExecuteSecure(() => timer4.Start());
                    ExecuteSecure(() => progressBar1.Value = 0);
                    foreach (var file in listBox5.Items)
                    {
                        if (textBox5.Text == "0")
                        {
                            ExecuteSecure(() => button1.Visible = true);
                            string obj = Convert.ToString(file);
                            try
                            {
                                ExecuteSecure(() => label4.Text = obj);
                                    try
                                    {
                                        using (var md5 = MD5.Create())
                                        {
                                            using (var stream = new BufferedStream(File.OpenRead(obj), 720000000))
                                            {
                                                var md5Check = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "‌​").ToLower();
                                                string md5key = Convert.ToString(md5Check);
                                                textBox6.Text = md5key;
                                                if (listBox2.Items.Contains((textBox6.Text)))
                                                {
                                                    ExecuteSecure(() => listBox4.Items.Add(obj));
                                                    string threatcount = Convert.ToString(listBox4.Items.Count);
                                                    ExecuteSecure(() => textBox3.Text = foundcount);
                                                    ExecuteSecure(() => label3.Text = "Liczba znalezionych: " + foundcount);
                                                }
                                            }                              
                                        }
                                    }
                                    catch
                                    {

                                    }
                            }
                            catch
                            {

                            }

                            string filecount2 = Convert.ToString(listBox5.Items.Count);
                            int scnnr = Convert.ToInt32(textBox2.Text);
                            scnnr = scnnr * 1 + 1 * 1;
                            ExecuteSecure(() => textBox2.Text = Convert.ToString(scnnr));
                            ExecuteSecure(() => label2.Text = "Znaleziono: " + scnnr + " z " + filecount2);
                            int step = Convert.ToInt32(textBox2.Text);
                            int final = Convert.ToInt32(textBox1.Text);
                            int precent = 0;
                            precent = (step * 100) / (final * 1);
                            ExecuteSecure(() => textBox4.Text = Convert.ToString(precent));
                            ExecuteSecure(() => progressBar1.Value = precent);
                            ExecuteSecure(() => CheckShieldLauncher.Properties.Settings.Default.ScanProgress = Convert.ToString(precent) + "%");
                        }
                        else
                        {
                            Scanner.Properties.Settings.Default.ScanStatus = "Gotowe!";
                            Scanner.Properties.Settings.Default.ScanProgress = "0%";
                        }
                    }
     
                }, token);

Chodzi mi o to, że program wykonuje ten kod wykorzystując tylko 1 wątek (Drugi wątek odpowiada za aktualizację informacji w oknie programu) i robi to bardzo wolno przy okazji zawieszając się np. na pliku 573 z 1 938. Pliki są różnego typu od wielkich po takie małe i nawet na małych plikach po 100 KB program potrzebuje po kilka sekund na przeliczenie MD5. Jak można to udoskonalić?

Pozdrawiam!

(mr-owl) #2

Co to za koszmarek, może napisz co ten kod ma działać bo tutaj widzę tylko jakieś spaghetti. Używa tutaj jakiś dziwnych operacji. Umieść na GitHubie kod programu który da się skompilować i wtedy się zobaczy.

Pozdrawiam,

mr-owl

1 Like
(jestemszpieg) #3

Jeśli chcesz przyspieszyć ten kod, zalecam naukę programowania xd

(1niez) #4

Wiesz, właśnie się uczę a kto pyta nie błądzi…

(1niez) #5

Wiem, że ideał to nie jest. Kod umieszczę nieco później, ale koncepcja jest taka, że tym programem chcę rozpoznawać pliki. Mam bazę MD5 i program ładuje ją a następnie wczytuje listę plików i każdy po kolei porównuje z bazą. Jak znajdzie no to podbija liczbę znalezionych obiektów by pokazać wyniki potem.

(uspy12) #6

Zlicz ile masz plików (czy rekordów w bazie), potem podziel kod na zadania (po 50, 100,1000 rekordów, ile będzie trzeba i gdzie będzie najlepsza wydajność). Potem musisz podzielić to na zadania (task). Każdy task będzie ogarniał tylko część danych z bazy (tu uwaga, baza danych zakłada blokady na odczyt/zapis, musisz doczytać).

Z tego co rozumiem, za każdym razem odwołujesz się do bazy. Dużo przyspieszysz jeśli pobierzesz sobie wszystkie rekordy. Program pobierze Ci tylko raz wszystkie dane do cache i będzie z tym porównywał pliki (dużo szybsze na poziomie pamięci RAM -> pomijasz czas potrzebny na stworzenie query, jego wysłanie, odbiór…).

Do tego podziel kod na metody. Masz za dużo zagnieżdżeń.

(1niez) #7

Czyli zrobić parę Task.Factory.New? Jak pobrać te rekordy za jednym zamachem do cache?

Ewentualnie mógłbym poprosić o jakiś przykład? Tak jak wspominałem jestem nieco laikiem. :stuck_out_tongue:

(uspy12) #8

Ło Panie. Dobra. Jeśli używasz entity framework, to wybierz wszystko, co jest w danej tabelce do zmiennej (i już masz dane 2 cache). Sprawdzasz ile masz tam danych metodą count dostępną dla list. Robisz tablicę dynamiczną i wrzucasz tam dane podzielone z listy. Zwykły for od 0 do tego, ile zwróciło count.
Po zakończeniu, robisz listę Tasków I dodajesz tam metodę task, która dostanie jakiś zakres z tej tablicy. Odpalasz wszystkie task I patrzysz jak świat płonie. BTW, powinno się obejść bez task factory. Oczywiście, podany sposób nie jest optymalny, można pominąć tablicę. Dodałem ją, abyś miał łatwiej ogarnąć co się tam dzieje.

(1niez) #9

Okej tablice zrobię bez problemu. To jak ogarnąć te zadania bez task factory? Zależy mi też na tym aby ładnie podliczało ile plików z danej puli zostało sprawdzone.

(mr-owl) #10

Kurcze, zacznij do tego że całość oddzielisz od UI, wydziel metody funkcjonalne które odpowiadają za atomowe operacje, nazwij je sensownie i teraz posiadając moduły składaj całość do postaci działającego programu. Ciągle czekam na wersję którą da się pobrać z GitHub-a.

Pozdrawiam,

mr-owl

(1niez) #11

Sorki, że tak długo minęło od odpowiedzi. Ustaliłem w czym tkwi problem na podstawie kilku prób i funkcja hashująca nie problemów. Za długo trwa porównywanie tych 100 tysięcy obiektów z listboxa. Jest może inny sposób na sprawdzenie czy listBox zawiera dany obiekt? Pies jest pogrzebany w tym Contains całym.