Opóźnianie działania pętli z możliwością przerwania działania programu

0

Witam,
W C# nadal się uczę. Tym razem przyszło mi się zmierzyć z opóźnieniem pętli. Dotychczas stosowałem systemowy thread i podawałem czas na jaki ma być zwieszony proces. Problem w tym, że nie mogę zatrzymać działania programu w trakcie obliczeń. Muszę czekać, aż się wykona. Jakiej procedury można użyć, która będzie opóźniać działanie pętli z możliwością wcześniejszego przerwania programu?? Proszę o wyrozumiałość ponieważ dopiero się uczę. Znalazłem coś z timerem ale nie potrafię tego samemu zaaplikować może ma ktoś w swojej twórczości już jakiś przykładowy programik (mały -samo zaaplikowanie opóźniacza), gdzie jest taka procedura zaaplikowana??
Pozdrawiam

0

Obliczenia które muszą się wykonać są w tej pętli która chcesz zatrzymać? Jeśli nie to możesz któreś z tych odpalić asynchronicznie i wtedy przystopować jeden wątek.

0

Tzn to jest tak. Mam pętle w której mam obliczenia prowadzone. W pętli tej znajduje się wywołanie funkcji, która wyświetla wynik obliczeń na formie. Po wyświetleniu mam threda na kilka sec. Wszystko idzie jednym wątkiem, bo nie za bardzo jeszcze ogarniam wielowątkowość (cze się). Chcę to opóźnienie zrobić tak, żeby program w trakcie obliczeń reagował na przyciśnięcie przycisku stop na formie, a nie jak do tej pory (trzeba czekać do końca obliczeń bo nic nie działa).

0

No to obliczenia wywołaj w osobnym wątku wtedy nie będą blokować.

0

Problem w tym, że właśnie niezbyt ogarniam te wątki...inaczej się tego obejść nie da?

0

Można bez wątków, ale program będzie się "zawieszać" podczas wykonywania jednego kroku pętli. Tak więc jeśli ten krok wykonuje się szybko (<100ms) to bez problemu obejdzie się bez wątków. Ale jeśli krok obliczeniowy trwa dłużej to program będzie miał "czkawkę" - na wszelkie kliknięcia będzie reagować z opóźnieniem (nie zareaguje dopóki nie skończy aktualnie wykonywanego kroku obliczeniowego).

Proponuje rozwiązanie podobne do tego z timer'em czyli zamiast wykonywać obliczenia jednym cięgiem dzielimy je na małe kroczki i wykonujemy te kroczki co jakiś czas, tak aby aplikacja mogła porobić inne rzeczy między kroczkami. Z tym, że zamiast timera (głupie rozwiązanie!) użyj zdarzenia Application.Idle. Zdarzenie to jest wyzwalane wtedy, kiedy aplikacja nie ma nic do roboty - wtedy kiedy obsłuży wszystkie kliknięcia itd. i ma chwilę oddechu. Tak więc podepnij pod to zdarzenie funkcję która wykonuje pojedynczy kroczek obliczeniowy.

Jak już ogarniesz Application.Idle proponuję jednak zainteresować się wątkami i synchronizacją. Ważna dziedzina w programowaniu.

0

Witam,
Czy może mi ktoś coś wyjaśnić...a mianowicie mam funkcję, w której co jakiś czas wywołuję funkcje poniżej:

private void Rysowanie()
        {
            BackgroundWorker pauseExecution = new BackgroundWorker();
            pauseExecution.DoWork += new DoWorkEventHandler(MetodaPauzowania);
            pauseExecution.RunWorkerAsync();

            GraphPane myPane1 = zedGraphControl2.GraphPane;
            zedGraphControl2.GraphPane.CurveList.Clear();
            myPane1.Title.Text = "Metoda";
            myPane1.XAxis.Title.Text = "x";
            myPane1.YAxis.Title.Text = "y";

            if (OnOffreczne.Checked == true)
            {
                myPane1.XAxis.Scale.Min = Xmin;
                myPane1.XAxis.Scale.Max = Xmax;
                myPane1.XAxis.IsVisible = true;
                myPane1.YAxis.Scale.Min = Ymin;
                myPane1.YAxis.Scale.Max = Ymax;
                myPane1.YAxis.IsVisible = true;
            }
            if (OnOffSkalowanie.Checked == true)
            {
                Graphics g = zedGraphControl2.CreateGraphics();
                myPane1.XAxis.ResetAutoScale(myPane1, g);
                myPane1.YAxis.ResetAutoScale(myPane1, g);
            }

            myPane1.XAxis.MajorGrid.IsVisible = true;
            myPane1.YAxis.MajorGrid.IsVisible = true;

            LineItem myCurve0 = myPane1.AddCurve("", List10, Color.Blue, SymbolType.Circle);
            myCurve0.Line.Width = 2;
            myCurve0.Symbol.Fill = new Fill(Color.Red);

            zedGraphControl2.AxisChange();
            zedGraphControl2.Invalidate();
            zedGraphControl2.Refresh();

            do
            {
              Application.DoEvents();
            } while (pauseExecution.IsBusy);
            
        } 

Pytanie brzmi...czemu tak ciężko reaguje mi przycisk zatrzymania rysowania?? Raz kliknę i zadziała, raz kliknę i nie...według mnie szybkość obliczeń jest na tyle duża, że powinienem trafiać głównie w Application.DoEvents(); ponieważ czasy sięgają od 2 do 10 i wiecej sekund...a obliczenia idą w milisekundach jak nie mniej...

Zauważyłem teraz, że przycisk działa zawsze przy 2 naciśnięciu. Nie potrafię sobie tego wytłumaczyć. Dodam, że ustawione zostało zdarzenie na przyciśnięcie przycisku...
Odpalanie co jakiś czas funkcji odpada. Już mi ręce opadają...jak działa jedna metoda, to już program nie reaguje na przyciski;/ teraz po dodaniu backgroudworkera program ma "czkawke" jak inaczej można sprawdzać czy podczas działania drugiego wątku zostało coś wciśnięte na formatce?

Teraz zauważyłem, że jak mam prowadzoną animację, to pierwsze naciśniecie przycisku powoduje zmianę koloru (podświetlenie), drugie uruchamia zdarzenie _Click. Czy da się jakość programowo go podświetlić? po uruchomieniu Animacji tak aby z dwóch kliknięć zrobić jedno?

0

Przeczytaj uważnie to: http://msdn.microsoft.com/en-us/library/4852et58 a potem przeanalizuj przykład kodu (bardzo, bardzo prostego kodu) na samym dole strony, który realizuje dokładnie to co chcesz zrobić, czyli: wykonuje sobie jakieś obliczenia w wątku nie wieszając całego programu i umożliwia ich przerwanie, dodatkowo raportuje postęp obliczeń.

Gdy już zrozumiesz ten opis, będziesz wiedzał jak to się robi zamiast się domyślać. Na tym etapie (do wykonania tak prostej rzeczy) i przy użyciu BackgroundWorkera nie ma tu nic trudnego ani niezrozumiałego, nawet żadnej synchronizacii nie potrzeba

1 użytkowników online, w tym zalogowanych: 0, gości: 1