Podmienianie obrazków, stopwatch i przeładowanie okienka

0

Witam sz. Forumowiczów!

Mam malutki problemik i nie daję już rady, wysiadam, z powodu braku znajomości WindowsForms i kiepskiej znajomości wzorca MVP (tak jak umiem, tak go stosuje).

Scenariusz na podstawie Corsi Blocks:
Mam w oknie panel 800x600 px, zawsze wyśrodkowany. W panelu znajduje się 12 pictureboxów, jako obrazki przedstawiające płytkę, jak do szachownicy koloru dajmy na to żółtego. Wszystko wygląda jak po prostu wyłożony panel płytkami [równo].
W kodzie ustawiam setery na obrazki.
Teraz presenter: dajmy na to, ze naciskam spacje i się uruchamia 1 level. Model wypluwa tablice 4 liczb w zakresie od 0 do 11, oczywiście wylosowanych.
Reszta w kodzie:

             
if (m_model.IsFieldSelectable)
                return;

            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
            foreach (int item in m_model.RandomNumberFields)
            {            
                

                Console.WriteLine(item);
                switch (item)
                {
                    case (int)IndexField.First:
                        m_view.FirstField = m_model.RandomField;
                        break;
                    case (int)IndexField.Second:
                        m_view.SecondField = m_model.RandomField;
                        break;
                    case (int)IndexField.Third:
                        m_view.ThirdField = m_model.RandomField;
                        break;
                    case (int)IndexField.Fourth:
                        m_view.FourthField = m_model.RandomField;
                        break;
                    case (int)IndexField.Fifth:
                        m_view.FifthField = m_model.RandomField;
                        break;
                    case (int)IndexField.Sixth:
                        m_view.SixthField = m_model.RandomField;
                        break;
                    case (int)IndexField.Seventh:
                        m_view.SeventhField = m_model.RandomField;
                        break;
                    case (int)IndexField.Eigth:
                        m_view.EigthField = m_model.RandomField;
                        break;
                    case (int)IndexField.Ninth:
                        m_view.NinthField = m_model.RandomField;
                        break;
                    case (int)IndexField.Teenth:
                        m_view.TeenthField = m_model.RandomField;
                        break;
                    case (int)IndexField.Eleventh:
                        m_view.EleventhField = m_model.RandomField;

                        break;
                    case (int)IndexField.Twelfth:
                        m_view.TwelfthField = m_model.RandomField;
                        break;
                        
                }
                
                int i = 0;
                while (true)
                {
                    Console.WriteLine(i);
                    if (stopwatch.ElapsedMilliseconds > 1000)
                        break;
                    i++;
                }
                stopwatch.Restart();

            }
stopwatch.Stop();

Stopwatch się wykonuje, ale obrazki się dopiero podmieniają w momencie kiedy kod wyjdzie z foreach, a chcę żeby za każdym przebiegiem pętli się podmieniał obrazek.

Jakieś pomysły i łatwe w wykonaniu rozwiązania? Jestem początkujący w c#.

0

Mam takie pytanie czy przypadkiem nie masz problemu z zamarzaniem aplikacji?

0

Jeśli dobrze zrozumiałem to wystarczy, że uruchomisz funkcje odpowiedzialną za kolory w osobnym wątku.

1

@Degusto nie powinno się dawać takich rad. Osobny wątek to ciężka sprawa. Moim zdaniem powinien użyć Timera (tego z WindowsForms) i sobie dobrze poukładać w głowie co chce osiągnąć.
Co do samego odrysowywania to przyda się wywoływanie invalidate.

0

Co do uszczegółowienia. Większość klas w Net. nie jest przystosowana do "gwałcenia" ich z różnych wątków (aby to zrozumieć należy poczytać sobie o race condition). Ponieważ dodatkowo kontrolki są szczególnie złożonymi bytami domyślnie przy próbie odwołania się do nich z innego wątku zgłaszany jest wyjątek (dokładnie to w przypadku wywołania niektórych metod z kontrolki, a większość zmian powoduje wywołanie tych metod) można to zgłaszanie wyjątku wyłączyć ale nie powinno się tego robić.
Co do rozwiązań:

  1. nie stosować wątków jeżeli to nie jest potrzebne (pod wątkiem mam na myśli też Task i inne wynalazki typy System.Threading.Timer) w tym przypadku da się chociaż kod straci trochę na czytelności

  2. Stosować wszelakiego typu ułatwiacze np. async i await, BackgroundWorker, metody Invoke, BeginInvoke (w WindowsForms w kontrolce a w WPF w klasie Dispatcher)

  3. Bawić się w ręczne kolejkowanie, blokowanie zasobów - nieprzyjemna sprawa osobiście jakbym miał się czymś takim zajmować żądałbym dużych pieniędzy i zapewnienia na piśmie że nie ponoszę odpowiedzialności za szkody wynikłe z używania tego kodu.

  4. Osobny wątek i wyłączenie CheckForIllegalCrossThreadCalls dobre gdy masz ostatni dzień w pracy i szef mówi że cię nie wypuści pÓÓÓÓki nie pozbędziesz się zamarzania aplikacji.

0

@szogun1987, ogólnie masz rację, ale jak użyć async i await nie używając Task?

0

Trochę nie zbyt wyraźnie to wyartykułowałem, chodziło mi o przypadek gdy flaga CheckForIllegalCrossThreadCalls zostanie ustawiona na True i zamiast klasy Thread użyjemy ThreadPool albo Task.Start nie tworzymy wątku w sposób jawny co nie oznacza że nie będziemy mieli problemu z Race condition czy z cache procesora.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.