Laden...

asp.net und Threads

Erstellt von schuppsl vor 15 Jahren Letzter Beitrag vor 12 Jahren 3.686 Views
S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 15 Jahren
asp.net und Threads

Hallo.

Ich habe in meiner alten C++ ISAPI Anwendung per Socket Daten abgeholt.
Das mache ich nun genau gleich mit einer ASP.NET Anwendung.
Die Funktion, die die Daten abruft lief in einem eigenen Thread um zu vermeiden, daß bei einer blockierung des Sockets die ganze Anwendung hängen bleibt.
Kam der Thread nach einer bestimmten Zeit nicht zurück, wurde er abgebrochen und eine Fehlermeldung ausgegeben.

Das möchte ich jetzt gerne in meiner ASP Anwendung auch machen.

Einen Backgroundworker gibt es ja leider nicht, den Threadpool soll man nicht benutzen und sonst habe ich schon mit diesem hier rumgeschlagen:
Asynchrone Seiten mit ASP

Doch finde ich keine Möglichkeit eine Funktion in einem neuen Thread zu starten und auf diesen zu warten.(wie in C++)

Wie kann man so etwas bewerkstelligen?

Also einfach:

  • Thread erstellen, Threadfunktion ausführen
  • Auf Rückgabewert warten
  • bei Zeitüberschreitung abbrechen.

Wäre über Tips dankbar.

Grüße schuppsl

3.971 Beiträge seit 2006
vor 15 Jahren

Stichwort Ajax.

Du lieferst die Webseite als quasi Template an den Browser. Mit JavaScript holst du dir alle x-Sekunden die entsprechenden neuen Werte per Xml und zeigst diese anschließend an.

Im Hintergrund kann beispielsweise auch ein zusätzlicher Thread laufen und die Daten entsprechend schonmal Cachen und vorbereiten.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 15 Jahren

Ja gut, aber die Frage ist doch, wie ich die Threads erstelle:

Also einfach:

  • Thread erstellen, Threadfunktion ausführen
  • Auf Rückgabewert warten
  • bei Zeitüberschreitung abbrechen.

schuppsl

3.971 Beiträge seit 2006
vor 15 Jahren

Japp genauso. Mit einem Ajax-Request das zu machen, wäre auch möglich, allerdings bekommt dann anschließend nur ein Client die Daten.

Deshalb lieber sein seperaten Thread, der die Daten in einer Liste cached und der Ajax-Request sich nur die Werte aus der Liste holt.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

Also ich habe nun ein Snippet gefunden und angepasst:

 AutoResetEvent signal = new AutoResetEvent(false);

                       // Wird benötigt da ThreadPool verwendet wird:
                       Thread t = null;

                       // Durch diese Variante gibt es den Vorteil dass 
                       // die Worker-Methode nicht geändert werden muss.
                       ThreadPool.QueueUserWorkItem((o) =>
                       {
                           // Auf ThreadPool-Threads kann normalerweise nicht 
                           // zugegriffen werden. Mit diesem "Trick" gehts.
                           t = Thread.CurrentThread;

                           // Worker starten:
                           cy.ReceiveT(); 

                           // Benachrichtigen dass Worker fertig ist:
                           signal.Set();
                       });


            System.Threading.Timer tim = new System.Threading.Timer((o) => { signal.Set(); }, null, 5000, Timeout.Infinite);
            
            signal.WaitOne();

            if (t != null && t.IsAlive)
                t.Abort();

            
            string myBack = cy.recErg;

taugt das was oder nicht?
Es scheint ja zu funktionieren....

Aber sollte ich wirklich einen Thread vom Threadpool nehmen?

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo,

Aber sollte ich wirklich einen Thread vom Threadpool nehmen? Nein! Näheres dazu hier: Don’t use the ThreadPool in ASP.NET

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

16.807 Beiträge seit 2008
vor 12 Jahren

Man muss aber dazu sagen, dass man sich um den Queue der Threads absolut selbst kümmern muss, da man ansonsten ganz schnell in eine MemoryException rutschen kann!
ThreadPool nimmt das einem ab.

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

Man muss aber dazu sagen, dass man sich um den Queue der Threads absolut selbst kümmern muss, da man ansonsten ganz schnell in eine MemoryException rutschen kann!
ThreadPool nimmt das einem ab.

...hatte da doch noch was im Hinterkopf =)

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

Man muss aber dazu sagen, dass man sich um den Queue der Threads absolut selbst kümmern muss, da man ansonsten ganz schnell in eine MemoryException rutschen kann!
ThreadPool nimmt das einem ab.

Aber wenn ich einen erstellten Thread nach der Ausführung der Funktion wieder beende bzw abbreche dürfe doch nichts passieren, oder?

16.807 Beiträge seit 2008
vor 12 Jahren

Jeder Thread kostet Dich 1 MB RAM, der sofort belegt wird - der wird natürlich beim Abbrechen wieder verworfen.
Du bist aber gezwungen, eine Queue zu basteln, damit Du nur den zur Verfügung stehenden RAM nicht sprengst.
1000 zeitgleiche Zugriffe = 1000 Threads = 1000 MB RAM.

Du kannst **NIE **davon ausgehen "ach, wird schon nicht passieren".
Das sind dann genau die Situationen, die sich bei der Software-Wartung bezahlt machen.

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo,

ThreadPool nimmt das einem ab. Dass der ThreadPool seine Annehmlichkeiten hat, ist ja auch auf der verlinkten Seite beschrieben. Dennoch ist er für die Benutzung mit ASP.NET nicht unbedingt geeignet und sollte nicht verwendet werden, weil ASP.NET den ThreadPool intern auch zum servieren der Seiten nutzt.
Natürlich muss man wie bei allen anderen selbst erzeugten Threads selbst dafür sorgen daß sie richtig laufen und sich irgendwann unter Freigabe ihrer Ressourcen auch beenden. Da hilft einem aber auch der ThreadPool nichts.

Aber wenn ich einen erstellten Thread nach der Ausführung der Funktion wieder beende bzw abbreche dürfe doch nichts passieren, oder?

Wenn Du das oben genannte beachtest, sollte es bis auf die von Abt genannten Grenzen der Hardware keine Probleme geben.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

ok, das ist interessant!

Also es geht ja aktuell (wieder darum), daß ich per socket Daten von einer (eigenen) Software abfrage.
Habe schon viel mit stream.BeginRead usw versucht, aber nichts hilft wirklich.

Es ist so, daß die Software unter bestimmten Umständen zwar sendebereitschaft sendet, (vom Client aus gesehen also "es sind Daten zum Lesen vorhanden") dann aber nichts kommt.
Sollte zwar nicht so sein, ist aber (derzeit) noch selten der Fall.

In so einem Fall möchte ich eben die Socketabfrage in einem eigenen Thread starten und 2-3 Sekunden warten. KOmmt dann nichts, soll der Thread abgebrochen werden.
Mache ich das nicht so, blockiert der Socket bis zum Sankt Nimmerleins-Tag und die Webanwendung ist nicht mehr bedienbar, außer durch Abbruch.

Mit BeginRead sollte man sowas ja eigentlich machen können oder?
Habe aber keinen Erfolg damit.

Aktuell sieht mein Tread nun so aus:


ThreadStart t = new ThreadStart(cy.ReceiveT);
             Thread myT = new Thread(t);
             myT.Start();
             myT.Join(15000);
             myBack = cy.recErg;

Mit Join warte ich auf den Thread. Blockiert der Socket nach der verstrichenen Zeit nicht, soll der Thread abgebrochen werden.

Ist sowas (bis auf den Queue) praktikabel?

Wie groß ist denn der Threadpool eigentlich?

Wir haben bisher in unserer C++ Application (ISAPI-DLL) einen Threanqueue von 50 Threads, was bisher immer gereicht hat...

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo,

Wie groß ist denn der Threadpool eigentlich?

Standardmäßig sind das 25 Threads bis .NET 3.5, ab Version 4.0 hängt die Standardgröße auch vom System ab.
Schau Dir mal die statischen Methoden in der ThreadPool-Klasse an, da kannst Du die Anzahl auslesen und auch setzen.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

Okidoki, aber ist das so wie oben gebräuchlich?

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo,

Du musst noch die Rückgabe des Join-Aufrufs auswerten und im false-Fall den Thread selbst beenden. Sonst sieht's soweit OK aus - sind 15s Timeout nicht etwas lang für 'ne Webanwendung?

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

Doch sind 15 Sekunden zu viel, war nur zum Test.
Ich denke 2 Sekunden dürften genügen.
Die Auswertung habe ich inzwischen gemacht.

Dann machen ich mich mal an den ThreadQueue:-)

Vielen lieben Dank für die Anmerkungen und Eure wertvolle Zeit!

3.170 Beiträge seit 2006
vor 12 Jahren

Hallo schuppsl,

um nochmal hierdrauf zurückzukommen:

In so einem Fall möchte ich eben die Socketabfrage in einem eigenen Thread starten und 2-3 Sekunden warten. KOmmt dann nichts, soll der Thread abgebrochen werden.

Das sollte aber doch auch anders möglich sein. Du bekommst ja vermutlich einen NetworkStream.
Dann kannst Du die NetworkStream.ReadTimeout-Eigenschaft setzen und direkt mit Read lesen, im Timeout-Fall wird dann eine IOException geworfen, die Du fangen müsstest. So kannst Du Dir den eigenen Thread komplett sparen.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 12 Jahren

Hallo MarsStein,

das hatte ich schon versucht, hat aber nicht funktioniert, d.h. der Networkstream hat Blockiert...

16.807 Beiträge seit 2008
vor 12 Jahren

Um mal zurück zum Thema zu kommen.

Wie schaut denn eine hier optimale Queue für Threads aus? Mich würden die Meinungen interessieren.
Die meisten Queues arbeiten Blind mit einer fixen Anzahl von Threads; ohne die vorhandenen Ressourcen zu beachten.
Die vorhandenen Ressourcen zu erkennen ist aber im ASP Bereich bekanntlich aufgrund der mangelnden Rechte auf Hardware-Informationen schwer.

Ich arbeite selbst mit einer fixen Anzahl aber glücklich bin ich damit auch nicht; die Maschine hat etliche GB Speicher und ich nehm einfach mal an die stehen mir auch zur Verfügung. Das funktioniert; aber auch nur weil ich die Maschine alleine für mich habe.
Würde gerne so viele Threads - wie die Maschinen verträgt + Puffer - arbeiten lassen, um möglichst jedes bisschen Performance ausnutzen zu können und weitere Überprüfungen vermeiden.

Macht es hier sinn PFX zu nutzen?
Inwiefern könnte es Probleme geben? Restriktionen von Parallel.ForEach ?