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();
}
}
}