Ereignisbasierte asynchrone Muster
Frank Dzaebel, erstellt am: 12.06.2007, zuletzt geändert: 12.06.2007
Kategorie:Implementation, .NET-Version:2.0, [Download]

Hier zwei Test-Projekte zu einem Code-Beispiel aus der MSDN. Bei beiden Projekten kann während der Berechnung nicht der Abbrechen-Button gedrückt werden, da die Berechnung die MessageLoop blockiert. Ersetzt man Thread.Sleep(0) in allen Projekten auf Thread.Sleep(1), funktioniert das dann. Im Beispiel wird es allerdings enorm langsam, sodass die Zahl 12345 benutzt werden sollte, um einen Effekt zu sehen.



Literatur:
Exemplarische Vorgehensweise: Implementieren einer Komponente, die das ereignisbasierte asynchrone Muster unterstützt

using System;
using System.Windows.Forms;
using System.ComponentModel;

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

    private void Form1_Load(object sender, EventArgs e)
    {
      primeNumberCalculator1.CalculatePrimeCompleted += new CalculatePrimeCompletedEventHandler(
        primeNumberCalculator1_CalculatePrimeCompleted);
      primeNumberCalculator1.ProgressChanged += new ProgressChangedEventHandler(
        primeNumberCalculator1_ProgressChanged);
    }

    void primeNumberCalculator1_ProgressChanged(ProgressChangedEventArgs e)
    {
      progressBar1.Value = e.ProgressPercentage;
    }

    private void btnBerechnen_Click(object sender, EventArgs e)
    {
      int zahl; progressBar1.Visible = true; Application.DoEvents();
      if (int.TryParse(txtZahl.Text, out zahl))
        primeNumberCalculator1.CalculatePrimeAsync(zahl, 1);
      else
        MessageBox.Show("Geben Sie eine Zahl ein!", "Falsches
          Zahlenformat",
          MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }

    void primeNumberCalculator1_CalculatePrimeCompleted(object sender, CalculatePrimeCompletedEventArgs e)
    {
      progressBar1.Visible = false;
      if (e.Error != null)
      {
        MessageBox.Show(e.Error.Message, "Berechnung fehlgeschlagen",
          MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        return;
      }
      if (e.Cancelled)
      {
        MessageBox.Show("Die Berechnung wurde vom Benutzer abgebrochen", "Berechnung abgebrochen",
          MessageBoxButtons.OK, MessageBoxIcon.Information);
        return;
      }
      if (e.IsPrime)
      {
        MessageBox.Show("Die Zahl " + e.NumberToTest + "
          ist eine Primzahl!", "Primzahl",
          MessageBoxButtons.OK, MessageBoxIcon.Information);
        return;
      }
      if (e.FirstDivisor != 1)
      {
        MessageBox.Show("Die Zahl " + e.NumberToTest + "
          ist keine Primzahl.\r\n" +
          "Sie ist durch " + e.FirstDivisor + " teilbar.", "Keine Primzahl",
          MessageBoxButtons.OK, MessageBoxIcon.Information);
        return;
      }
    }

    private void btnAbbrechen_Click(object sender, EventArgs e)
    {
      primeNumberCalculator1.CancelAsync(1);
    }
  }
}