Laden...

Deserialisierung duch User canceln

Erstellt von cyc vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.767 Views
C
cyc Themenstarter:in
3 Beiträge seit 2010
vor 13 Jahren
Deserialisierung duch User canceln

Hi,
Gibt es die Möglichkeiten eine laufende Deserialisierung mit BinaryFormater in C# zu canceln (z.B. wenn User auf Escape Taste drückt)?
Wurde bei meiner Suche leider weder in der Doku noch mit Google fündig.
Würde mich freuen falls mir da jemand weiterhelfen bzw. in die richtige Richtung leiten könnte.
Grüße,
Timo

5.742 Beiträge seit 2007
vor 13 Jahren

Hallo cyc,

herzlich willkommen hier auf myCSharp.de!

Gibt es die Möglichkeiten eine laufende Deserialisierung mit BinaryFormater in C# zu canceln (z.B. wenn User auf Escape Taste drückt)?

Nein - die gibt es nicht.
So eine Möglichkeit würde aber auch nicht wirklich viel Sinn machen, da der BinaryFormatter sowieso nur für "kleinere" Datenmengen konzipiert ist. Diese sollte er dann in weniger als einer Sekunde abarbeiten können.

Evtl. blockiert etwas anderes bei dir so lange?

Oder deine Datenmengen sind einfach zu groß - in diesem Falle solltest du erwägen, auf eine Datenbank auszuweichen. Diese sollten da um einiges performanter zu Werke gehen.

Was serialisierst bzw. deserialisierst du denn?
Evtl. lassen sich ja auch manche Daten weglassen.

C
cyc Themenstarter:in
3 Beiträge seit 2010
vor 13 Jahren

Die Daten sind binär serialisiert maximal ca. 40 mb (Messdaten) groß und schon soweit reduziert, dass sie nur das nötigste enthalten.
Leider ist die Vorgabe, dass dass Programm ist keine Datenbank verwendet soll.
Bisher war ich mit der binären Serialisierung recht zufrieden (z.B. über eine Wrapperklasse war es mir möglich eine ProgressBar upzudaten und Geschwindigkeitsprobleme konnte ich durch geignetes Datenlayout in den Griff bekommen).

Ich denke ich habe jetzt eine Lösung gefunden:
Die Idee ist hier folgende und baut auf die ReadProgressStream und ContainerStream Klasse aus folgendem Artikel auf:
.NET Matters: Deserialization Progress, and More

zusätzlich definiere ich eine Exception falls von Aussen die Deserialisierung Unterbrochen wurde:


    public class DeserializationException : System.ApplicationException
    {
        public DeserializationException() { }
        public DeserializationException(string message) { }
        public DeserializationException(string message, System.Exception inner) { }

        // Constructor needed for serialization 
        // when exception propagates from a remoting server to the client.
        protected DeserializationException(System.Runtime.Serialization.SerializationInfo info,
            System.Runtime.Serialization.StreamingContext context) { }
    }

Zusätzlich nehme ich folgende Änderungen vor:


    public bool canceled = false; // neu !!!!!!!!
    public override int Read(byte[] buffer, int offset, int count)
    {
        if (canceled) throw new DeserializationException();  // neu !!!!!!!!

        int amountRead = base.Read(buffer, offset, count);
        if (ProgressChanged != null)
        {
            int newProgress = (int)(Position * 100.0 / Length);
            if (newProgress > _lastProgress)
            {
                _lastProgress = newProgress;
                ProgressChanged(this, 
                    new ProgressChangedEventArgs(_lastProgress, null));
            }
        }
        return amountRead;
    }

Hiermit ist die Deserialisierung von Aussen (ProgressChangedEvent handler) abbrechbar.
Hoffe damit jemand helfen zu können falls er auf das selbe Problem stösst.

Grüße,
Timo

3.430 Beiträge seit 2007
vor 13 Jahren

Hallo,

Die Daten sind binär serialisiert maximal ca. 40 mb (Messdaten) groß und schon soweit reduziert, dass sie nur das nötigste enthalten.
Leider ist die Vorgabe, dass dass Programm ist keine Datenbank verwendet soll.

Serialisierung ist schon eine nette sache aber 40MB sind IMHO ein bisschen zu viel des Guten.

Es gäbe auch die lokalen Datenbanken die ohne Installation und Server funktionieren.
z.B. SQL Compact, Firebird...

Vielleicht kannst du sowas ja verwenden denn damit könntest du um einiges konfortabler arbeiten weil du nur die Daten laden musst die du auch brauchst.

Gruss
Michael

S
72 Beiträge seit 2009
vor 13 Jahren

Hallo cyc,

man sollte Exceptions nicht verwenden um den Programmfluss zu steuern.
Abgesehen davon, sollte man keine öffentlichen Felder machen. Verletzt die Kapselung der OO.

C
cyc Themenstarter:in
3 Beiträge seit 2010
vor 13 Jahren

Ja geb ich zu ist eher ein Hack.
Dient eher dazu zu zeigen, dass es grundsätzlich möglich ist.
Habt ihr einen Vorschlag wie ich ohne Exception in diesem Fall auskomme?
Grüße
Timo

1.044 Beiträge seit 2008
vor 13 Jahren

Hallo cyc,

noch einfacher wäre es mit LINQ to XML. Dort hast du auch dir Möglichkeit zum Streamen. Und Parallelisieren ist auch möglich. Serialisierung würde ich persönlich nicht verwenden.

zero_x

N
46 Beiträge seit 2007
vor 13 Jahren

Hallo Stefan O.,

man sollte Exceptions nicht verwenden um den Programmfluss zu steuern.

Immer dieses dogmatische Denken. Ich steuere IMMER den Programmfluss, sobald ich eine Exception werfe. Darf ich jetzt nach Deiner Aussage folgend niemals eine Exception werfen?

Den aktiven Abbruch eines lang laufenden Prozesses durch den Benutzer halte ich für einen absolut legitimen Grund, eine Exception zu benutzen. Das ist aus meiner Sicht auch kein Hack.

MfG,

N1ls

742 Beiträge seit 2005
vor 13 Jahren

Natürlich werden mit Exceptions auch der Programmfluss gesteuert, aber nur wenn es nicht anderst geht, wenn eben eine Exception auftritt, die man nicht vorhersehen konnte.

Zum Beispiel bevorzuge ich:


if (File.Exists(myFile))
{
   using (FileStream stream = new FileStream(myFile, FileMode.Open))
   {
      ...
   }
}
else
{
   // Error Handling, Whatever
}

anstatt


try
{
   using (FileStream stream = new FileStream(myFile, FileMode.Open))
   {
      ...
   }
}
catch (FileNotFoundException)
{
   // Error Handling, Whatever
}

Ich würde in deinem Fall auf jeden Fall ein Event Cancelled oder so erstellen.

5.299 Beiträge seit 2008
vor 13 Jahren

ABer beim Serialisieren geht da nix, weil man kein Fuß dazwischen kriegt.
cyc hat da schon eine schlaue Lösung mit einem speziellem Stream, aber wenn man dessen Lesevorgang mw. sauber vorzeitig beendet, schmeißt eben der BinaryFormatter eine Exception, weil er das Objekt nicht bilden kann.

Der frühe Apfel fängt den Wurm.

5.742 Beiträge seit 2007
vor 13 Jahren

man sollte Exceptions nicht verwenden um den Programmfluss zu steuern.

Zum Abbrechen eines Vorganges halte ich die Verwendung von Exceptiosn schon legitim - macht ja auch CancellationToken.

1.820 Beiträge seit 2005
vor 13 Jahren

Hallo!

Wie wäre es mit der Auslagerung in einen eigenen Thread? Somit ist zum einen die UI nicht blockiert, und mit Thread.Abort ist ein Abbruch möglich.

Nobody is perfect. I'm sad, i'm not nobody 🙁

5.742 Beiträge seit 2007
vor 13 Jahren

Thread.Abort

Deprecated 😉

F
10.010 Beiträge seit 2004
vor 13 Jahren

@malignate :
Files und andere Öffentlich zugängliche Objekte sind ein sehr schlechtes Beispiel für diese Herangehensweise.
Wenn zwischen deinem File.Exists und dem Zugriff die Datei "verschwindet" hast du ein Problem.
Also bei Files, kannst du gleich auf die Exception gehen, ansonsten ist es aber sicherlich richtiger erst abzufragen, als ins Messer zu laufen.

@N1ls:
Nur wenn man verstanden hat, was man wo, warum macht/nicht macht, kann man von Pragmatismen abweichen, aber sie von Vornherein zu verneinen zeigt auch ein gewisses Unverständnis.

B
48 Beiträge seit 2010
vor 13 Jahren

Hallo,
Serialisierung ist schon eine nette sache aber 40MB sind IMHO ein bisschen zu viel des Guten.

Warum?

742 Beiträge seit 2005
vor 13 Jahren

@FZELLE: Vielen Dank für den Hinweis, obwohl es so offensichtlich ist, habe ich bisher nie daran gedacht.

Fühle mich gerade richtig blöd.