Verfasst von: bletra | 6. April 2011

.Net: Prozess, Thread, AppDomain

Bei Hanselman habe ich mal einen Artikel gelesen, was gute .Net-Entwickler wissen sollten. Unter anderen sollten diese die Begriffe Prozess, Thread und AppDomain erklären und voneinander abgrenzen können. Hier meine Antwort – aus Windowssicht.

Prozesse bekommen Sie im Task-Manager aufgelistet. Prozesse haben etwas mit dem Betriebssystem und Applikationen zu tun. In den heutigen Betriebssystemen können mehrere Prozesse gleichzeitig laufen, sie verfügen über eine eindeutige Prozessid und einen eigenen (virtuellen) Speicherraum. Ein Prozess ist ein Programm (eine Applikation) in der Ausführung. Ein Prozessor führt in jeder Zeiteinheit genau einen Prozess aus, d.h. die lange Liste im Taskmanager bei auch nur einem Prozessor bedeutet: Das System wechselt zwischen den einzelnen Prozessen, es entscheidet, wann welcher Prozess ausgeführt wird.

Threads sind leichtgewichtige Prozesse. In einem Prozess können mehrere Threads gleichzeitig laufen, die sich den entsprechenden Adressraum teilen, aber verschiedene Stacks nutzen. Bei Windows-Systemen werden Threads auch Tasks genannt.

.Net kennt noch eine weitere in diesem Zusammenhang relevante Technologie, die AppDomains. AppDomains werden auch als Pseudoprozesse oder Prozesse der CLR (Common Language Runtime) bezeichnet. Sie können als eine Art Sandbox genutzt werden. Geht innerhalb einer anderen AppDomain etwas schief (Exception), dann stürzt die eigentliche Applikation (Prozess) nicht ab. AppDomains werden sind sinnvoll, wenn Sie fremden Code, z.B. Add-Ins, in Ihre Applikation integrieren möchten.

Im Folgenden möchte ich die Unterschiede zwischen AppDomain und Thread in C# an einem Codebeispiel erläutern. Ich habe dazu eine Console-Applikation und eine Klassenbibliothek (UBTAppDomain) erstellt. In der Klassenbibliothek wird eine Ausnahme geworfen:

namespace UBTAppDomain
{
 public class MyClass : MarshalByRefObject
 {
   public void Crash()
   {
     Console.WriteLine("UBTAppDomain thread: " + Thread.CurrentThread.Name);
     Console.WriteLine("UBTAppDomain thread id:" + Thread.CurrentThread.GetHashCode());
     Console.WriteLine("main thread app domain: " + System.AppDomain.CurrentDomain.FriendlyName);
     throw new Exception("this is an exception from UBTAppDomain!");
   }
 }
}

In meiner Consolen-Applikation habe ich eine Referenz auf dieses Projekt hinzugefügt und zunächst einen neuen Thread gestartet:

Console.WriteLine("main thread: {0}", Thread.CurrentThread.Name);
Console.WriteLine("main thread id: {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("main thread app domain: {0}", AppDomain.CurrentDomain.FriendlyName);
UBTAppDomain.MyClass crashClass = new MyClass();
try
{
  Thread t = new Thread(new ThreadStart(crashClass.Crash));
  t.Start();
}
catch (Exception e)
{
  ...
}

Wird dieser Code ausgeführt, so wird die Exception geworfen und nicht in Zeile 10 gefangen! Die Ausgabe auf der Console zeigt die verschiedenen Thread-Ids bei gleicher AppDomain.
Mit Threads habe ich also keine Möglichkeit fremden Code sicher einzubinden. Dafür muss ich eine neue AppDomain erzeugen und den Code darin laufen lassen, wie folgendes Listing zeigt:

System.AppDomain sandboxDomain = System.AppDomain.CreateDomain("Sandbox");
try
{
  //execute an exe with newDomain.ExecuteAssembly("AppDomain.exe");
  UBTAppDomain.MyClass crashClassInAppDomain = (UBTAppDomain.MyClass)sandboxDomain.CreateInstanceAndUnwrap("UBTAppDomain", "UBTAppDomain.MyClass");
  crashClassInAppDomain.Crash();
}
catch (Exception ex)
{
  Console.WriteLine("exception: " + ex.Message);
}
finally
{
  // Unload the application domain:
  System.AppDomain.Unload(sandboxDomain);
}

Nun wird die Ausnahme, wie gewünscht gefangen und die Anwendung stürzt nicht ab. Auf der Console werden die verschiedenen AppDomains bei gleichem Thread ausgegeben.
Wichtig: Um Objekte zwischen verschiedenen AppDomains zu übermitteln (Zeile 5) muss die zugehörige Klasse entweder als „Serializable“ markiert sein oder von „MarshalByRefObject“ erben (siehe erstes Listing).

Sie können diesen Teil auch in eine Methode auslagern und diese in einem neuen Thread starten.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Kategorien

%d Bloggern gefällt das: