Hallo peoples!
Ich verzweifel gerade etwas am SynchronizationContext. Ich habe mir einiges an Material angeschaut und meint Mentor kennt sich auch ganz gut aus, leider ist Letzterer zZt. nicht verfügbar - ich möchte aber trotzdem den Kram auf die Reihe bekommen.
Der SC (so kürze ich es mal ab) funktioniert laut meiner Recherche so, dass er den jegliche Anweisungen einer async Method nach einem await in ein callback Objekt packt und es, wenn man es in der implementation einer geerbten Klasse nicht ändert, in den Threadpool wirft.
Soweit so gut. Nun habe ich meine eigene Implementation geschrieben welche von SO erbt:
internal class Synchronizer : SynchronizationContext
{
private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, Object>> callbackQueue;
public Synchronizer()
{
callbackQueue = new BlockingCollection<KeyValuePair<SendOrPostCallback, Object>>();
}
public override void Post(SendOrPostCallback d, object state)
{
callbackQueue.Add(new KeyValuePair<SendOrPostCallback, Object>(d, state));
}
public void ProcessAwaits()
{
KeyValuePair<SendOrPostCallback, Object> currentItem;
while (callbackQueue.TryTake(out currentItem))
currentItem.Key(currentItem.Value);
}
}
soweit so gut...
Nun habe ich eine Klasse welche einen Mainloop ausführt. In diesem MainLoop wird eine InputHandler Methode aufgerufen welche eine async Methode ist und aus Testzwecken nur ein Task.Delay(2000) ausführt und awaited - im Anschluss aber auch eine Console.Write() anweist. Laut SC Prinzip müsste dieses Console.Write() "gepackt" werden und via die SC.Post() Method implizit weggeschifft werden. Im Anschluss könnte ich diesen Kram dann wieder in dem Thread synchron abarbeiten lassen wo ich das möchte.
Nun einmal die InputHandler Klasse:
public sealed class ConsoleInputField : ConsoleField, IInputHandler
{
public ConsoleInputField(Int32 x, Int32 y, Int32 width, Int32 height, String name)
: base(x, y, width, height, name)
{
}
public async void HandleInput()
{
await Task.Delay(2000);
Console.Write("Peter der Meter");
}
}
und einmal die Hauptklasse:
public static class ConsoleGUI
{
private static Synchronizer synchronizer = new Synchronizer();
private static IInputHandler focused = new ConsoleInputField(1,1,1,1,"Hässelhoff");
public static void Loop()
{
while(true)
{
focused.HandleInput();
SynchronizationContext lastContext = Synchronizer.Current;
Synchronizer.SetSynchronizationContext(synchronizer);
synchronizer.ProcessAwaits();
Synchronizer.SetSynchronizationContext(lastContext);
}
}
}
Beim debuggen wird die Post Methode nie aufgerufen - demnach macht SC nicht das was es soll. Was verpasse ich hier? Sorry Jungs aber google spuckt so wenig Infos über SC aus.
gruß Charlie
Hallo,
versuch mal, Deinen SynchronizationContext umzubiegen, bevor Du die asynchrone Methode HandleInput aufrufst:
SynchronizationContext lastContext = Synchronizer.Current;
Synchronizer.SetSynchronizationContext(synchronizer);
focused.HandleInput();
synchronizer.ProcessAwaits();
Synchronizer.SetSynchronizationContext(lastContext);
Sonst landest Du im falschen Kontext!
Gruß, MarsStein
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca