Laden...

SynchronizationContext - Post-Methode wird nie aufgerufen

Erstellt von Falke2000 vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.368 Views
F
Falke2000 Themenstarter:in
21 Beiträge seit 2015
vor 8 Jahren
SynchronizationContext - Post-Methode wird nie aufgerufen

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

3.170 Beiträge seit 2006
vor 8 Jahren

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

F
Falke2000 Themenstarter:in
21 Beiträge seit 2015
vor 8 Jahren

Danke genau das war der Denkfehler!