Samstag, 31. Dezember 2011

Dezember 2011 / C#: Multithreading & ShowWindow aus WinAPI

Multithreading in C#

Was ist Multithreading und wann wir es gebraucht?
Unter Multithreading versteht man das abarbeiten mehrerer Threads gleichzeitig innerhalb eines Prozesses. Dadurch können mehrere arbeiten Parallel und auf einander abgestimmt ausgeführt werden.
Das heisst innerhalb eines Programmes können 2 Threads Daten austauschen aber auch gleichzeitig unabhängig voneinander arbeiten.

Dazu ein Beispiel:
Ich erstelle ein GUI mit einem grossen Textfeld, in welches der Benutzer irgendeinen Text eingeben kann. Ebenfalls kann man über das Menu die Farben des Form- und des Textbox-Hintergrundes ändern. Per Knopfdruck soll das Programm dann den eingegebenen Text mit dem Bubblesort(sehr langsam) alphabetisch sortieren.
Bei einem langen Text kann das schon einige Sekunden dauern. Möchte der Benutzer nun das Programm schliessen oder die Hintergrundfarben ändern, kann er das nicht, da die gesamte Rechenleistung des Threads beim Sortieren gebraucht wird.
Hier kommt das Multithreading zum Einsatz. Wird die Sortierung in einem 2. Thread erledigt, kann der Benutzer parallel dazu das GUI bedienen.

Multithreading in C#:
In C# kann ziemlich einfach ein weiterer Thread erstellt & gestartet werden.
Zuerst sollte man das using von System.Threading hinzufügen:
using System.Threading;

Sobald das gemacht ist kann man direkt mit Thread arbeiten und einen neuen Thread instanziieren:
Thread neuerThread = new Thread(this.Methode)

Als Parameter muss eine Methode mitgegeben werden, welche im neuen Thread ausgeführt werden soll.
Wichtig ist dabei, dass man keine Klammern hinter die Methode stellt, sonst gibt es eine Fehlermeldung.

Nun muss der neue Thread noch gestartet werden und auch das ist ganz simpel:
neuerThread.Start();

ShowWindow aus WinAPI

Die Windows API(Windows-Anwendungs-Programmierschnittstelle) bietet Windows-Programmierern viele Funktionen welche in DLL-Dateien gespeichert sind.
Eine solche Funktion ist ShowWindow, welche dazu verwendet wird Fenster zu Maxi-/Minimieren, zu verstecken, wieder anzuzeigen usw.
Ich stiess auf diese Funktion, als ich nach einer Möglichkeit gesucht habe, einen Virtuellen Computer dauerhaft versteckt im Hintergrund laufen zu lassen.
Um diese Funktion nutzen zu können muss die DLL user32.dll eingebunden werden und einer Variabel zugewiesen werden:
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
 
Wie man sieht hat ShowWindow 2 Parameter ein IntPtr Objekt und ein int.
IntPtr enthält in diesem Fall ein Window Handle, welches durch eine Zahl repräsentiert wird.
Mit dem int wird übergeben, was mit dem Fenster gemacht werden soll. Diese werden am besten direkt als globale Konstante deklariert. Die Liste der Möglichkeiten befindet sich am Ende des Posts.
 
Nun muss man natürlich das Window Handle von dem Prozess haben, auf dessen Fenster man Einfluss nehmen möchte. In meinem Fall war das der VMPlayer.
Dazu gäbe es eine GetWindow-Funktion, welche ebenfalls von der WinAPI bereitgestellt wird.
Besser ist es jedoch, das Window Handle über den Prozess zu holen und das funktioniert so:
IntPtr vmWindow = IntPtr.Zero;
 
Process[] processes = Process.GetProcessesByName("vmplayer");
 
foreach (Process p in processes)
{
    vmWindow = p.MainWindowHandle;
}
 
Zuerst wird hier vmWindow als IntPtr instanziiert.
Anschliessend wird an processes alle Prozesse mit dem Namen vmplayer übergeben. Da bei mir nur 1 virtueller PC läuft, wird auch nur 1 Prozess zurückgegeben.
Anschliessend wird das MainWindowHandle des gefundenen Prozesses an vmWindow übergeben.
 
Nun kann man über ShowWindow das Fenster verstecken, maximieren usw.
Hier wird das Fenster versteckt, vorausgesetzt SW_HIDE wurde als Konstante mit dem Wert 0 deklariert:
ShowWindow(vmWindow, SW_HIDE);
 
Hier noch die Liste mit den Möglichkeiten:
  • private const int SW_HIDE = 0 ' Versteckt das Fenster
  • private const int SW_SHOWNORMAL = 1 ' Zeigt das Fenster und aktiviert dies
  • private const int SW_SHOWMINIMIZED = 2 ' Zeigt das Fenster an und Minimiert es
  • private const int SW_MAXIMIZE = 3 ' Maximiert das Fenster
  • private const int SW_SHOWNOACTIVATE = 4 ' Zeigt das Fenster an ohne es zu aktivieren
  • private const int SW_SHOW = 5 ' Zeigt das Fenster an, auch wenn es versteckt ist
  • private const int SW_MINIMIZE = 6 ' Minimiert das Fenster
  • private const int SW_SHOWMINNOACTIVE = 7 ' Minimiert das Fenster aber aktiviert es nicht
  • private const int SW_SHOWNA = 8 ' Zeigt das Fenster an aber aktiviert es nicht
  • private const int SW_RESTORE = 9 ' Stellt das Fenster wieder her

Keine Kommentare:

Kommentar veröffentlichen