Archiv des Tags ‘Delegate’

Part II: Mimic SynchronizationContext behaviour on .NET CF

Sonntag, den 15. Februar 2009

I just posted the second part of the article Part I: Mimic SynchronizationContext behaviour on .NET CF on planetgeek.ch! On the article I try to show how the basic behavior of the SynchronizationContext can be achieved on the .NET compact framework platform. Please refer to the article under:

http://www.planetgeek.ch/2009/02/15/part-ii-mimic-synchronizationcontext-behaviour-on-net-cf/

Part I: Mimic SynchronizationContext behaviour on .NET CF

Sonntag, den 8. Februar 2009

Before I got into the details of the problem I want to briefly describe what the SynchronizationContext class really does and what it’s main purpose really is in the first part of the article. From that perspective I’m going to show how the basic functionality of the SynchronizationContext class can be implemented for the .NET compact framework in the second part of the article..

The msdn library documentation states:

Provides the basic functionality for propagating a synchronization context in various synchronization models.

I must admit the first time when I read this definition I didn’t really get the key point behind the SynchronizationContext class. Detailed look into the implementation of SynchronizationContext and its base classes provided me the following information:

The SynchronizationContext class is a class belonging to the System.Threading namespace. The SynchronizationContext provides a model to make the communication between threads easier and more robust especially if multiple threading contexts/apartments such as “UI threading context” etc. are present.

To get a deeper understanding of the definition above I want to give you a short example. Imagine if you have a separate thread performing an intense calculation such as calculating the n-th Fibonacci number. When the separate thread has finished its long running operation you want to display the n-th Fibonacci number on a user interface. Normally (without using the SynchronizationContext class) you would need to do the following (or at least something similar):

private delegate void FibonacciResultDelegate(long fibonacciResult);
 
private void MethodCalledByTheFibonacciThread(long fibonacciNumber)
{
   if( fibonacciResultTextBox.InvokeRequired)
   {
      FibonacciResultDelegate fibonacciDelegate =
         MethodCalledByTheFibonacciThread;
      fibonacciDelegate.Invoke(this, new object[] { fibonacciNumber });
      return;
   }
   fibonacciResultTextBox.Text = fibonacciNumber.ToString();
}


With the SynchronizationContext class we can invoke delegates in the context of a different thread. For the example above we could do the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class FibonacciPresenter
    {
        private readonly Thread workerThread;
 
        private readonly SynchronizationContext context;
 
        private readonly IFibonacciView fibonacciView;
 
        public FibonacciWorker(IFibonacciView view)
        {
            fibonacciView = view;
 
            context = SynchronizationContext.Current;
 
            workerThread = new Thread(new ThreadStart(FibonacciCalc));
 
            workerThread.Start();
        }
 
        private void FibonacciCalc()
        {
            long result = CalculateFibonacciNumber( ... );
            context.Post(new SendOrPostCallback(delegate(object state)
            {
               fibonacciView.DisplayResult(result);
            }), null);
        }
 
        // details omitted...
    }

In code line 13 we can see how the SynchronizationContext is retrieved. The SynchronizationContex.Current property points to the SynchronizationContext of the thread where the FibonacciWorker was created (in my example the FibonacciWorker would be created in a control). Then the FibonacciCalc method can post (asynchronous) or send (synchronous) a SendOrPostCallback delegate containing the “job” which needs to be marshaled over the SynchronizationContext. Therefore the line fibonacciView.DisplayResult(result) would be invoked on the UI thread which allows us to remove the “invoke required” code parts and directly set the fibonacci calculation result to the textbox text property.

We can briefly summarize that the purpose of the SynchronizationContext is to post (asynchronous) or send (synchronous) SendOrPostCallback delegates in the correct threading context which simplifies marshaling.

Delegate.DynamicInvoke for .NET Compact Framework

Sonntag, den 18. Januar 2009

As you might already know I’m a certified windows mobile application developer. My speciality is hybrid application development for applications which target both the full .NET framework platform and also the mobile platform. Of course nobody wants to write the same code for each platform again so you have to come up with some tricks and solutions to overcome some limitations on the compact framework.

One such limitation is the missing Delegate.DynamicInvoke method. The Delegate.DynamicInvoke method allows to dynamically invoke delegates late-bound. That means normally when you are invoking a method via a delegate you actually need to have knowledge about the target type where the delegate gets executed. With Delegate.DynamicInvoke this is not longer necessary. The beauty of this is, that you can have base code like the following:

// Elsewhere
RegisterDelegate(SomeClass.SomeMethod);
RegisterDelegate(SomeOtherClass.SomeOtherMethod);
FireForAllWith(1, 2, 3, 4);
 
// Code in some utility
public void FireForAllWith(params object[] args)
{
   someGenericCollection.ForEach(dlg => dlg.DynamicInvoke(args));
}
public void RegisterDelegate(Delegate dlg)
{
   someGenericCollection.Add(dlg);
}

But if you try to use Delegate.DynamicInvoke in the compact framework your infrastructure code will not compile because for some obscure reasons microsoft decided not to implement Delegate.DynamicInvoke for .NET compact framework. Here is my solution to this problem:

I created an extension method for the delegate class with the name DynamicInvoke. This extension method uses a small trick to implement the DynamicInvoke behaviour of the full framework platform.

    public static class DelegateExtensions
    {
        public static object DynamicInvoke(this Delegate dlg, params object[] args)
        {
            return dlg.Method.Invoke(dlg.Target, BindingFlags.Default, null, args, null);
        }
    }

As you can see I’m using the delegates method property which returns a MethodInfo object. On the MethodInfo I’m able to call Invoke and pass the arguments to the bound method. But the problem here is that Invoke requires a target where the method gets executed. This is where the delegates target property comes into play. That’s the whole magic and you’re able to dynamically invoke late bound methods via Delegate.DynamicInvoke.

Download DelegateExtensions for the source code.

Richtiges Invoke von UI Controls

Samstag, den 19. Januar 2008

Zu diesem Thema gibt es meiner Meinung nach im Netz nicht viel schlaue Links und Hinweise, da wollte ich mal ein bisschen aufräumen. Aber zuerst einmal um was es da genau geht.

Wenn man mit dem Visual Studio ein GUI erstellt und auf diesem GUI zum Beispiel eine Textbox hinzufügt , diese GUI dann kompiliert und ausführt, dann laufen alle GUI Operationen im sogenannten Main- oder auch UI-Thread. Dieser Thread ist zuständig für das richtige Updaten, Zeichen etc. der Benutzerelemente.

Programmiert man eine Funktion die viel Rechenzeit braucht und führt diese Funktionen in einem neuen Thread aus, so muss man die Crossthreadingcalls beachten, wenn man aus dem neu erstellten Thread auf die Benutzerelemente des Mainthreads zugreifen will (um zum Beispiel in der Textbox einen Text hinzuzufügen). Denn greift man ohne zusätzliche Sicherheit einfach aus dem zweiten Thread auf das Text Property der Textbox zu, so kann aus unter Umständen dazu führen, dass zwei Thread s zur gleichen Zeit auf die Textbox zugreifen und es kommt zu unvorhersagbaren Verhalten auf dem GUI. Doch wie kann man dies umgehen?

Die Lösung heisst Delegates und Control.Invoke().

Nehmen wir an wir haben eine Methode MyMethod du jedesmal wenn Sie von einem anderen Thread aufgerufen wird auf dem GUI den Text eines Labels myControl auf “Vom Thread aufgeweckt!” setzt. Damit die Methode MyMethod threadsafe aufgerufen werden kann, muss folgendes Codesegment implementiert werden:

Methode ohne Parameter und zugehöriges Delegate

Private delegate void MyMethodDelegate();
Private void MyMethod() {
	if(myControl.InvokeRequired) {
		myControl.Invoke(new MyMethodDelegate(MyMethod));
		return;
	}
	// Add rest of the code here
        myControl.Text = "Vom Thread aufgeweckt!";
}

Der Ablauf des obigen Codesegments ist folgendermassen. Man definiert ein Delegate (quasi typensicherer Methodenpointer), das später auf die Methode MyMethod “zeigt”. Danach prüft man in der eigentlichen Methode über myControl.InvokeRequired ob das Control aus einem anderen Thread angesprochen wurde. Ist dies der Fall, so führt man ein Invoke auf myControl über myControl.Invoke mit dem Delegate MyMethodDelegate durch und übergibt dem Delegate die aufgerufene Methode (hier MyMethod) als Parameter. Nach dem Invoke verlässt man die Methode direkt wieder über die Anweisung return;. Der eigentliche Zugriff auf das Control myControl erfolgt dann im Codeblock // Add rest of the code here.

Die Logik dahinter ist, dass durch den Aufruf von Inkvoke auf das Control, wird über das Delegate die Methode nach einmal aufgerufen und der zugreifende Thread meldet sich quasi beim UI-Thread an und wartet, bis dieser den Zugriff auf das Control frei gibt. Sobald dies der Fall ist, kann der Thread in die Methode und dieses Mal ist das Flag InvokeRequired auf false gesetzt und es wird nur der eigentliche Codeblock bei // Add rest of the code here ausgeführt.

Doch wie funktioniert das Ganze, wenn die Methode MyMethod ein oder mehrere Parameter entgegen nimmt? Hier ist der Codeauszug:

Methode mit Parameter und zugehöriges Delegate

Private delegate void MyMethodWithParameterDelegate(string message);
Private void MyMethodWithParameter(string myParameter) {
	if(myControl.InvokeRequired) {
		myControl.Invoke(new
MyMethodWithParameterDelegate(MyMethodWithParameter), new object[]{ myParameter });
		return;
	}
	// Add rest of the code here
        myControl.Text = myParameter;
}

Der Ablauf ist wieder genau gleich, einfach wird in diesem Fall ein Delegate mit Parameter spezifiziert und beim Invoke wieder ein Delegate erstellt und die Parameter für die Methode als Objektarray übergeben. That’s it!

Viel Spass beim Ausprobieren…