Asynchroner Aufruf aufräumen
-
Hallo,
ich hab gerade mal eine Klasse erstellt und ein bisschen mit asynchronen Methodenaufrufen und Events gespielt.
Hier mal mein Code:
using System; using System.Globalization; using System.Threading; using System.Windows; namespace Async { public partial class MainWindow { private readonly AsyncClass _asyncClass1; private readonly AsyncClass _asyncClass2; public MainWindow() { InitializeComponent(); _asyncClass1 = new AsyncClass(); _asyncClass1.GetDataFinished += param1 => MessageBox.Show(param1.ToString(CultureInfo.InvariantCulture), "Caption 1"); _asyncClass2 = new AsyncClass(); _asyncClass2.GetDataFinished += param1 => MessageBox.Show(param1.ToString(CultureInfo.InvariantCulture), "Caption 2"); } private void Button1Click(object sender, RoutedEventArgs e) { _asyncClass1.GetData(double.Parse(textBox1.Text)); _asyncClass2.GetData(double.Parse(textBox1.Text)); } } public class AsyncClass { public delegate void GetDataEventHandler(double param1); public event GetDataEventHandler GetDataFinished; private readonly GetDataEventHandler _sfd; private static Object _semaphore; public AsyncClass() { _semaphore = new object(); _sfd = SomeFunction; } public void GetData(double value) { _sfd.BeginInvoke(value, null, null); } private void SomeFunction(double param1) { lock(_semaphore) { double product = param1; for (int i = 0; i < param1; i++) { product *= param1; } Thread.Sleep(5000); OnGetDataFinished(product); } } private void OnGetDataFinished(double value) { GetDataEventHandler handler = GetDataFinished; if (handler != null) { handler(value); } } } }
Jetzt mal eine Frage... Könnte man die Klasse "AsyncClass" noch weiter bereinigen und aufräumen oder ist da schon das Maximum erreicht?
-
Hallo.
In SomeFunction findet die eigentliche Arbeit statt.
Möchtest Du nun für jede Methode, die Du asynchron ausführen willst, einen solchen Aufstand machen?Gutes Design wäre, den veränderbaren Teil (SomeFunction) irgendwie auszulagern.
Erstmal mit C#-Mitteln im wesentlichen das, was Du gemacht hast:
static double Worker(double param1) { double product = param1; for (int i = 0; i < param1; i++) { product *= param1; } return product; } static void Main(string[] args) { Func<double, double> async = Worker; async.BeginInvoke(5, IAsyncResult => { Func<double, double> res = (Func<double, double>)IAsyncResult.AsyncState; Console.WriteLine(res.EndInvoke(IAsyncResult)); }, async); }
Schön wäre nun eine wiederverwendbare Lösung. Vielleicht so:
static void Async<T, TRes>(T t, Func<T, TRes> asyncWorker, Action<TRes> callback) { asyncWorker.BeginInvoke(t, IAsyncResult => { Func<T, TRes> res = (Func<T, TRes>)IAsyncResult.AsyncState; callback(res.EndInvoke(IAsyncResult)); }, asyncWorker); }
Edit: Etwas kürzer
static void Async<T, TRes>(T t, Func<T, TRes> asyncWorker, Action<TRes> callback) { asyncWorker.BeginInvoke(t, IAsyncResult => callback(asyncWorker.EndInvoke(IAsyncResult)), null); }
Dann genügt ein einfacher Aufruf:
Async<double, double>(5, Worker, (res => Console.WriteLine(res)));
um den Parameter (5) asynchron an die Worker-Methode zu übergeben. Das dritte Argument
ist das Callback sobald die Methode fertig ist.Vielleicht kann man das ganze jetzt noch für andere Parameterzahlen erweitern. Momentan funktioniert es nur
mit einem Parameter und einem Rückgabewert.
Auf jeden Fall kann man jetzt in einer Zeile machen, wofür Dein Ansatz ein paar dutzend Zeilen benötigt.Edit: Das ganze nur so als Idee. Es spricht nichts dagegen das ganze nochmal in eine Klasse zu packen und mit einem Event mehrere Observer zu realisieren.