Listing 1: Programmcode für das WPF-Fenster in Abbildung 2: Asynchrone Ausführung mit Abbruchoption
Anzeige
using System.Data;
using System.Data.SqlClient;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace WPF45
{
/// <summary>
/// Interaction logic for WPFDataAccessAsync.xaml
/// </summary>
public partial class WPFDataAccessAsync : Window
{
public WPFDataAccessAsync()
{
this.DataContext = this;
InitializeComponent();
}
/// <summary>
/// Dependency Property für Datenbindung an TextBlock C_Status
/// </summary>
public string Status
{
get { return (string)GetValue(StatusProperty); }
set { SetValue(StatusProperty, value); }
}
public static DependencyProperty StatusProperty =
DependencyProperty.Register("Status", typeof(string),
typeof(WPFDataAccessAsync), null);
/// <summary>
/// Verwaltungsobjekt für Abbruch der Aktion
/// </summary>
private CancellationTokenSource cts = null;
private async void C_Laden_Click(object sender, RoutedEventArgs e)
{
cts = new CancellationTokenSource();
Print("C_Laden_Click() #1: Aufruf wird initiiert.");
ReadDataAsync(cts.Token);
Print("C_Laden_Click() #2: Aufruf ist erfolgt.");
}
private void C_Abbrechen_Click(object sender, RoutedEventArgs e)
{
Print("Abbruch des Ladens wird eingeleitet...");
cts.Cancel();
Print("Laden ist abgebrochen!");
}
private void C_Ende_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
/// <summary>
/// Asynchroner Datenzugriff
/// Hinweis: Natürlich gehört Datenzugriffscode normalerweise nicht
/// in die Code-Behind-Datei. Aber hier soll es nur darum gehen, auf
/// übersichtliche Weise das TA-Pattern zu erklären
/// </summary>
private async Task<bool> ReadDataAsync(CancellationToken ct)
{
Status = "";
Print("Beginn ReadDataAsync");
// Datenbankverbindung asynchron aufbauen
var conn =
new SqlConnection(
@"data source=.;initial catalog=WWWings6;integrated security=True;
MultipleActiveResultSets=True;App=ADONETClassic");
await conn.OpenAsync(ct);
Print("Nach OpenAsync");
// Daten asynchron abrufen
var cmd = new SqlCommand("select * from flug", conn);
var reader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection,
ct);
Print("Nach ExecuteReaderAsync");
// Nur zum Test: Ausführungszeit künstlich verlängern, wenn die
// Datenbankabfrage zu schnell ist
for (int i = 0; i < 100; i++)
{
await Task.Delay(50);
if (ct.IsCancellationRequested)
{
Print("Laden wird abgebrochen!");
return false;
}
}
// Verpacken in DataTable zur Datenbindung an GridView
DataTable dt = new DataTable();
dt.Load(reader);
C_Daten.ItemsSource = dt.DefaultView;
// Verbindung beenden
conn.Close();
Print("Ende ReadDataAsync");
return true;
}
private void Print(string s)
{
int tid = System.Threading.Thread.CurrentThread.ManagedThreadId;
string ausgabe = s + " Thread=" + tid;
Status += ausgabe + "\n";
System.Diagnostics.Debug.WriteLine(ausgabe);
}
}
}