OpLock-Klasse

Leichtgewichtiger, nicht threadsicherer Sperrmechanismus, um die Ausführung der selben Operation durch mehrere Methoden gegenseitig zu sperren.

Diese Klasse kann verwendet werden, wenn sich mehrere Operationen in einer GUI- oder Single-Thread-Anwendung gegenseitig ausschließen. Im Gegensatz zum lock-Schlüsselwort von C# werden mehrere gleichzeitige Aufrufe nicht serialisiert, sondern vollständig verhindert. Anstelle den zweiten Aufruf abzubrechen kann auch jedes andere Verhalten implementiert werden, wie z. B. eine Interaktion mit der ersten laufenden Instanz. Da keine threadsichere Sperre verwendet wird, benötigt diese Klasse weniger Ressourcen und ist dadurch performanter. Außerdem ermöglicht die Nutzung eines OpFlags auch eine Abfrage des aktuellen Zustands der Sperre.

Kompatibilität: .NET Ab Version 2.0

Beispiel

Die folgenden Beispiele zeigen, wie die OpLock- und OpFlag-Klassen verwendet werden können. Im ersten Beispiel werden zwei gegenseitige TextBox-Updates gesperrt:

// Speichert den Sperrzustand des Textfelds
private OpFlag isUpdating = new OpFlag();
   
private void TextBox1_TextChanged(object sender, EventArgs e)
{
    // Zustand der Sperre prüfen und ggf. abbrechen
    if (isUpdating.IsSet) return;
    // Sperre setzen und Operation durchführen
    using (new OpLock(isUpdating))
    {
        // Durch diesen Aufruf wird die andere Ereignismethode aufgerufen, die
        // aufgrund der gesetzten Sperre aber nichts tut.
        TextBox2.Text = TextBox1.Text;
    }
}

private void TextBox2_TextChanged(object sender, EventArgs e)
{
    // Zustand der Sperre prüfen und ggf. abbrechen
    if (isUpdating.IsSet) return;
    // Sperre setzen und Operation durchführen
    using (new OpLock(isUpdating))
    {
        // Durch diesen Aufruf wird die andere Ereignismethode aufgerufen, die
        // aufgrund der gesetzten Sperre aber nichts tut.
        TextBox1.Text = TextBox2.Text;
    }
}

Das zweite Beispiel zeigt eine ViewModel-Klasse, in der das geöffnete Editorfenster den Import-Befehl sperrt:

// ViewModel-Klasse des Hauptfensters der WPF-Anwendung
class MainWindowViewModel : ViewModelBase
{
    // Referenz auf das Editorfenster
    private EditorWindow editorView;
    // Speichert den Sperrzustand des Editors
    private OpFlag editorFlag = new OpFlag();
   
    // Commands für das Anwendungsmenü
    public DelegateCommand EditorCommand { get; private set; }
    public DelegateCommand ImportCommand { get; private set; }

    // ViewModel-Konstruktor
    public MainWindowViewModel()
    {
        // Initialisieren der Commands
        EditorCommand = new DelegateCommand(OnEditorCommand);
        ImportCommand = new DelegateCommand(OnImportCommand, CanExecuteImport);

        // Wenn sich der Sperrzustand des Editors ändert, muss WPF darüber
        // informiert werden, dass sich die Verfügbarkeit des Import-Befehls
        // geändert hat.
        editorFlag.ValueChanged += (s, e) =>
        {
            ImportCommand.RaiseCanExecuteChanged();
        };
    }

    // Behandelt den Editor-Befehl
    private void OnEditorCommand()
    {
        // Wenn die Sperre gesetzt ist, ist das Editorfenster bereits geöffnet.
        // In diesem Fall muss es nur in den Vordergrund gebracht werden.
        // Andernfalls muss es neu erstellt und geöffnet werden.
        if (!editorFlag.IsSet)
        {
            // Neues Editorfenster erstellen
            editorView = new EditorWindow();
            // Weitere Initialisierung...
           
            // Die Sperre wird jetzt gesetzt
            editorFlag.Enter();
            // Freigeben der Sperre, wenn das Fenster geschlossen wurde
            editorView.Closed += (s, e) => { editorFlag.Leave(); };
            // Fenster anzeigen, nicht modal (das Hauptfenster ist weiter verfügbar)
            editorView.Show();
        }
        else
        {
            // Fenster fokussieren
            editorView.Focus();
        }
    }

    // Gibt an, ob der Import-Befehl derzeit zur Verfügung steht. Das ist immer
    // dann der Fall, wenn das Editorfenster nicht geöffnet ist.
    private bool CanExecuteImport()
    {
        return !editorFlag.IsSet;
    }

    // Behandelt den Import-Befehl
    private void OnImportCommand()
    {
        // ...
    }
}

Download

OpLock.cs2,4 KiBQuelltext der OpLock-Klasse

Lizenz und Nutzungsbedingungen

Vervielfältigung und Weiterverbreitung dieser Datei, verändert oder unverändert, sind gestattet, vorausgesetzt die Urheberrechtsangabe und dieser Hinweis bleiben erhalten. Diese Datei wird wie vorliegend ohne jegliche Garantie oder Gewährleistung angeboten. (GNU All-Permissive-Lizenz)

Statistische Daten

  • Erstellt am 2012-08-06.