| 

.NET C# Java Javascript Exception

6
Asynchron bedeutet ja in der Regel, dass ich eine Funktion aufrufe, dieser eine Callback-Funktion übergebe. Der Code läuft weiter. Gibt die asynchrone Funktion nun ein Ergebnis zurück, ruft sie die Callback-Funktion auf. Soweit, so gut.
Wenn ich aber mehrere solcher Aufrufe auf verschiedene asynchrone Funktionen habe, diese aber erst als erledigt gelten, wenn alle asynchronen Funktionen zurückgekehrt sind, wie mache ich das? Beispielsweise frage ich asynchron zwei Datenbanken ab. Erst wenn ich die Ergebnisse von beiden Abfragen habe, darf das Programm etwas mit den Daten anstellen.
15.02.2011
BooBoo 61 3
5 Antworten
4
Dein Beispiel deutet auf ein Fork/Join Pattern hin

Für deinen Fall gibt es die TPL (Task Parallel Library) :-)
Die hat so ziemlich alles für die Synchronisation Standard Szenarien Paralleler Verarbeitung.

Somit brauchst du dich nicht mehr manuell um Waithandles etc. kümmern.


Z. Bsp. :
Parallel.Invoke(
()=> MeineSelectMethode1()
,()=>MeineSelectMethode2)
);
//Verarbeite Ergebnisse aus 1 und 2


oder

Task[] tasks = new Task[3]
{
Task.Factory.StartNew(() => MethodA()),
Task.Factory.StartNew(() => MethodB()),
Task.Factory.StartNew(() => MethodC())
};

//Block until all tasks complete.
Task.WaitAll(tasks);


Nur um mal zwei Möglichkeiten zu nennen :)

Dann werden Task 1 und Parallel ausgeführt und erst wenn beide fertig sind der Folgecode ausgeführt.

http://msdn.microsoft.com/de-de/library/dd460717.aspx

Analog gibts dazu auch ein Parallel.Foreach usw...

In 3.5 kannst du diese via ReactiveFX verwenden, ab .net 4 dann direkt.

Ausserdem gibts dort einen Haufen an klassen für einfache Threadsynchronisation.
z.bsp. Task

Hier gibt es einen Webcastserie zur TPL: http://www.microsoft.com/germany/msdn/webcasts/serien/MSDNWCS-0905-01.mspx
15.02.2011
Gentlehag 1,0k 2 8
1
Es gibt dazu auch interaktive Beispiele (nur als Ergänzung zu der Antwort): http://www.wischik.com/lu/AsyncSilverlight/AsyncSamples.html wobei die auf private Space gehostet werden...
Hendrik Lösch 15.02.2011
2
z.B. mit WaitHandle.WaitAll

die MSDN hat auch ein ganz brauchbares Beispiel:

http://msdn.microsoft.com/de-de/library/z6w25xa6.aspx
15.02.2011
Matthias Hlawatsch 13,2k 4 9
0
Da gibt es viele Ansätze. Ich habe das über eine Basisklasse gelöst, die nach Verarbeitung asynchroner Aufrufe ein Event wirft.
#region Nested type: SynchronizeTasks

/// <summary>
/// synchonize server tasks
/// </summary>
public class SynchronizeTasks
{
#region Delegates

/// <summary>
/// delegate for notification
/// </summary>
public delegate void AllCompletedDelegate();

#endregion

/// <summary>
/// tasklist
/// </summary>
private readonly List<string> _tasks = new List<string>();

/// <summary>
/// notify-event
/// </summary>
public event AllCompletedDelegate OnAllCompleted;

/// <summary>
/// refresh tasklist and reset event
/// </summary>
public void Clear()
{
_tasks.Clear();
OnAllCompleted = null;
}

/// <summary>
/// add task
/// </summary>
/// <param name = "task"></param>
public void Add(string task)
{
_tasks.Add(task);
}

/// <summary>
/// task completed
/// </summary>
/// <param name = "task"></param>
public void Completed(string task)
{
if (_tasks.Contains(task))
{
_tasks.Remove(task);
if (!_tasks.Any())
{
//fire event when all tasks are completed
OnAllCompleted();
//clean up eventhandler for garbage collector
OnAllCompleted = null;
}
}
}
}

#endregion


So kann die Initialisierung der Tasks aussehen:
Tasks = new SynchronizeTasks();
Tasks.Add("DoSomething1");
Tasks.Add("DoSomething2");
Tasks.OnAllCompleted += Accomplished;

Über den Callback eines Tasks wird das OnPropertyChangedEvent geworfen. Darin befindet sich der Code, der die Taskliste über das Ende der Verarbeitung informiert:
if (Tasks != null)
{
Tasks.Completed(propertyName);
}

Befindet sich kein Task mehr in der Taskliste, wir das AllCompletedEvent geworfen.
Das ist ein Grundgerüst und lässt sich beliebig erweitern und ausbauen.
15.02.2011
Jürgen Luhr 7,1k 1 9
0
Parallel.Invoke gibt es von Haus aus nicht in Silverlight 4, oder?
15.02.2011
Florian Mätschke 370 1 7
Kenne mich wenig mit Silverlight aus aber glaube nicht, unter http://msdn.microsoft.com/en-us/library/dd992634.aspx ist bei den Version infos zumindest kein silverlight aufgeführt

s. a. http://forums.silverlight.net/forums/p/21522/353335.aspx#353335
Gentlehag 15.02.2011
-1
Ein Counter funktioniert hier ebenfalls wunderbar.

Wenn du 5 asynchrone Aufrufe startest:
setzt du den Counter auf 5, z.B. eine nicht lokale int Variable.
Bei jedem Callback ziehst du dann 1 vom Counter wieder ab und wenn der 0 ist, sind alle Callbacks durchgelaufen und du kannst dann weitermachen.


private int _counter;

private void Start()
{
_counter = 5;

//... 5 async methoden aufrufen
}

private void CallBack1()
{
_counter--;

// do stuff for callback 1

Resume();
}


//.
//..
//...

private void CallBackN()
{
_counter--;

// do stuff for callback N

Resume();
}

private void Resume()
{
if(_counter == 0)
{
// do your stuff here...
}
}
15.02.2011
Florian Mätschke 370 1 7

Stelle deine Datenbank-Frage jetzt!