Frage

Ich habe eine PropertyGrid in meiner Anwendung, die für die Bearbeitung beliebiger Objekte verwendet wird. Ich muss in der Lage sein, eine beliebige Unterprogramm auf einem anderen Thread ausgeführt werden, die auch bei diesen Objekten (Suchfunktion, wenn Sie neugierig sind) aussieht. Die offensichtliche Problem ist, dass ein Benutzer eines dieser Objekte Bearbeitung werden konnte meine Suche Thread es zur gleichen Zeit liest, die zu vermeiden, vorzuziehen wäre (obwohl es wahrscheinlich in etwas nicht kritisch führen wird, da meine Suche Thread gerade liest, nicht zu schreiben).

lock(obj) Aufruf ist einfach genug von meiner Suche Thread, aber nach durch die Dokumentation suchen und eine kurze Skim durch den PropertyDescriptorGridEntry Code in Reflector, kann ich nicht eine analoge Stelle zu finden scheinen System.Threading.Monitor.Enter()/Exit() Anruf auf das betreffende Objekt auf dem verwenden, Property. Ich hatte gehofft, es würde BeginEdit und EndEdit Ereignisse, die diese einfach genug machen würde, aber ich kann nicht so etwas zu finden scheinen. Ich möchte lieber nicht das gesamte Objekt sperren, während es in der Property auf dem Display ist wie das wäre offensichtlich meine Suche Thread blockiert, bis ein anderes Objekt ausgewählt wurde.

Ich bin ein bisschen neu auf dem Threading-Modell von Windows Forms, so hoffe ich, dass eine offensichtliche Antwort ist Ich habe gerade übersehen. Jede Hilfe?

Edit: Synchrone meiner Objekte klonen, bevor die Suche asynchron ausgeführt genug wahrscheinlich ineffizient sein wird, dass ich auch die Suche selbst synchron laufen könnte - der Punkt asynchron ausgeführt ist natürlich meinen Benutzer zu ermöglichen, weiter zu arbeiten, während die Suche ausgeführt wird. Die Suche muss gut skalieren, da die Daten stellen ich durchmache wird schließlich am Ende als beliebig groß, die synchrone Klonen macht aussehen, wie es das Usability-Problem verursachen wird ich zu vermeiden versuchen.

War es hilfreich?

Lösung

Ich glaube, Sie gehen zu müssen, für diese ziemlich viel Arbeit zu tun.

Als erstes müßten Sie eine Implementierung von ICustomTypeDescriptor zu schaffen, die ihre Umsetzung auf, was TypeDescriptor stützen würden Sie normalerweise für diese Art erhalten würden.

Dann in den Implementierungen der Methoden, die die Deskriptoren der Mitglieder Sie sperren auf möchten aussetzen, würden Sie Subklassen anbieten, die von Deskriptoren ableiten und die entsprechenden Methoden außer Kraft setzen, eine Sperre umwickeln.

Also für eine Eigenschaft, würden Sie GetProperties implementieren Ihre spezifischen Subklassen von PropertyDescriptor zurückzukehren. Diese Unterklassen würden die Methoden GetValue und SetValue außer Kraft setzen (und anderen) und eine Sperre verwenden, wenn diese Variablen zugreifen.

Es soll erwähnt werden, dass in dem UI-Thread wie diese Verriegelung ist wahrscheinlich eine schlechte Idee, da Sie nicht wollen, willkürlich Operationen auf diesem Thread blockieren. Es könnte besser sein, nur ein Klon des Objekts zu erstellen und dann ein Verfahren, das den Laden von Objekten aktualisiert, wenn Sie fertig sind.

Andere Tipps

Das wird in der Tat nicht Thread-sicher sein. Sie könnten Bits des Suchcodes auf dem UI-Thread Marschall, aber das wird die Dinge verlangsamen und vielleicht den Punkt des Gewindes besiegen ...

Wie schnell soll die Suche sein? Können Sie arbeiten gegen einen Klon? etc

Können Sie die Daten klonen, bevor diese angezeigt, und die Suche Thread auf dem Klon zu arbeiten? Wenn Sie die Suche Thread zu „sehen“ Änderungen wollen, können Sie auf Ereignisse auf dem PropertyGrid reagieren und vielleicht machen gesteuert Änderungen am Klon irgendwie. (Es ist wahrscheinlich einfacher, nur wenn die „veralteten“ Daten zu verwenden.)

Ich weiß, das Klonen Daten fürchterlich ineffizient klingen, aber Einfädeln einfacher sicher, wenn jeder Thread auf völlig unabhängige Daten arbeitet (oder alle Fäden nur lesen).

Ich könnte falsch sein, aber es scheint mir, dass Sie aus dem falschen Ende kommen.

Es gibt zwei verschiedene Fragen müssen Sie Adresse.

Erstens, um sicherzustellen, dass der Property wird immer nur auf dem UI-Thread abgerufen. Wenn eine ihrer Methoden (einschließlich Eigenschaft Getter / Setter) von anderen Threads zugegriffen wird, werden Sie Schmerzen auf mysteriöse Weise leiden. Die Ausnahmen sind InvokeRequired() und Invoke, natürlich.

Zweitens, sicherstellen, dass Ihre Suche Thread kann richtig ausgeführt werden.

Um das erste Problem zu lösen, entweder sicherstellen, dass Ihre Objekte werden nie geändert außer durch den UI-Thread, oder alle Ihrer Veranstaltung machen Trigger Thread bewusst, so dass Ihre Objekte Ereignisse (wie Property) sind immer nur auf dem UI-Thread ausgelöst.

Das zweite Problem ist einfacher - solange Ihre Suche Thread liest nur von Ihren Kernobjekten, sollte alles funktionieren. Ja, Ihre Suche Thread versehentlich möglicherweise einige teilweise aktualisierten Daten sehen, aber ist das wirklich ein Problem?

Ein paar abschließende Gedanken ...

  • Sie implementieren Ihre Suche nicht durch die Property iterieren selbst; erhalten eine Liste der Objekte vorne (sie brauchen keine Klone zu sein) und die Arbeit durch diese statt.

  • Haben Sie Idle Verarbeitung als mit der Suche zu tun? Das Application Objekt löst ein Ereignis jedes Mal die Anwendung von Nachrichten an Prozess läuft - Sie in diese Haken könnte, und führen Sie Schritt 1 Ihrer Suche jedes Mal das Ereignis ausgelöst wird. Art eines armen-mans Threading, aber mit keinem der Mutex / lock / Semaphore Kopfschmerzen. Ich habe diese auf sehr gute Wirkung in der Vergangenheit verwendet.

Aktualisieren : Wenn ich mich richtig erinnere, Property respektiert die IEditableObject Schnittstelle, ruft BeginEdit sobald Sie eine Zeile beginnen Ändern und

scroll top