Application.DoEvens - problemy z obsługą

0

Potrzebuję napisać program, który posiada nieskończoną, ale sterowaną pętlę (można ją wystartować i zatrzymać). Czas jednej iteracji ma być jak najkrótszy, więc w ramach pętli są tylko i wyłącznie instrukcje niezbędne do prawidłowej pracy algorytmu. Natomiast stan danych można "podglądać" za pomocą timera w odstępach rzędu pół sekundy, jedna sekunda.

Zauważyłem, że do tego najprościej i najlepiej będzie użyć Application.DoEvents zamiast bawić się wątkami.

Jednak jest mały problem.

Jeżeli kliknie się przycisk Start myszką, to jak się kliknie myszką w obrębie formularza, to nie wywoła się żadnej reakcji, tylko widać, jakbym jeszcze raz kliknął przycisk Start. Problem nie występuje, jak naprowadzę zaznaczenie klawiaturą (klawisz TAB) i wcisnę spacją przycisk.

Co ciekawe, jak do obsługi przycisku przed uruchomieniem pętli dopisze MessageBox.Show("xxx"); to problem znika, tylko, że w tym przypadku pokazywanie się komunikatu nie jest pożądane.

Gdzie szukać przyczyny problemu?

Przykładowy kod, w którym opisywany problem występuje:

// Na formie:
// button1 - przycisk START
// button2 - przycisk STOP
// textBox1 - do wyswietlania liczby
// timer1 - do odczytu i wyswietlenia liczby w textBox1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace DoEvents
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Okresla, czy program pracuje
        bool Working = false;

        // Przycisk "Start" - rozpoczecie pracy petli
        private void button1_Click(object sender, EventArgs e)
        {
            Working = true;
            ProgramWork();
        }

        // Przycisk "Stop" - zatrzymanie pracy petli
        private void button2_Click(object sender, EventArgs e)
        {
            Working = false;
        }

        // Liczba X "obrabiana" w zapetlonym programie
        uint X = 0;

        // Wlasciwa petla programowa, ktora ma byc sterowana
        void ProgramWork()
        {
            while (Working)
            {
                // Jakis algorytm jednej iteracji petli
                X = X + 1;
                if (X>2000000000)
                {
                    X = 0;
                }

                // Po to, zeby mozna bylo sledzic prace i zatrzymac petle
                Application.DoEvents();
            }
        }

        // Timer wyswietla aktualna liczbe X co 100ms
        private void timer1_Tick(object sender, EventArgs e)
        {
            textBox1.Text = X.ToString();
        }

    }
}
0
Bilski napisał(a)

Zauważyłem, że do tego najprościej i najlepiej będzie użyć Application.DoEvents zamiast bawić się wątkami.

Nie wiem gdzie to zauważyłeś, ale takich rzeczy nie robi się za pomocą Application.DoEvents(). Od tego masz wątki. Jak nie chcesz (lub też, aż takiej potrzeby nie masz potrzeby) z nich korzystać to wykorzystaj BackgroundWorkera do obliczeń.

0

Generalnie chodziło o to samo, co autorowi tego wątku:

http://4programmers.net/Forum/488950?h=doevents#id488950

Tylko, że nie ma tam żadnego kodu źródłowego, a tan z MSDN jest już bardziej skomplikowany, że istota sprawy w nim tonie.

Być może nie uruchamiał pętli przyciskiem, więc tego problemu nie miał.

Zauważyłem doświadczalnie, że pewnym rozwiązaniem problemu jest zmiana focus przy uruchamianiu procedury powiązanej z kliknięciem przycisku.

Wtedy przycisk Start wyglądałby następująco:

        private void button1_Click(object sender, EventArgs e)
        {
            button2.Focus(); //może być dowolny element, byleby inny niż klikany przycisk
            Working = true;
            ProgramWork();
        }

Wtedy po kliknięciu przycisku focus automatycznie się przenosi na drugi przycisk i problem nie występuje.

0

Zastanów się zatem jakie rozwiązanie cię interesuje. Czy warto trochę poszperać w google nt. BackgroundWorker'a i zrobić to tak jak przystało, czy lepiej ustawiać dziwnie focusy na kontrolkach aby zmusić do działania.

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