Thread::Suspend und Thread::Resume veraltet - wie richtig ersetzen
-
Hallo ihr Profis,
mein laienhaftes Programmieren hat bisher immer recht gut funktioniert, aber bei Multi-Threading hab ich bisher immer etwas in die Röhre geguggt. Ich war ganz froh, dass ich vor ein paar Jahren die Sache mit dem extra Rechen-Thread in meinem Programm hinbekommen habe. Nun hab ich das Programm in VS2008 portiert und dort bekomme ich beim Kompilieren die Meldung:
"Thread.Suspend has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources."
Das gleiche kommt für die Funktion Thread::Resume.Welche Befehle ersetzen die beiden veralteten? Das heißt, wie mach ich es jetzt wieder richtig.
Folgender Code lief bisher bei mir:
while(oThread->IsAlive) { //KeyAvailable checks message queue for keypress //returns true if a key has been pressed if(Console::KeyAvailable) { //Suspend thread oThread->Suspend(); //Read key cki = Console::ReadKey(true); Console::WriteLine(L"The fit has been paused! Do you really want to abort the regression?"); Console::WriteLine(L"Press ESCAPE to abort the thread other keys will continue."); //Read key cki = Console::ReadKey(true); if(cki.Key == ConsoleKey::Escape) { //Thread has to be continued before it can be aborted oThread->Resume(); oThread->Abort(); abortcontrol = true; break; } else oThread->Resume(); } }
Es wäre schön, wenn ihr mir da etwas auf die Sprünge helfen könntet.
Vielen Dank
physici
-
Hallo,
um einen Thread anzuhalten solltest du die Klasse Monitor verwenden. - In C# wäre es etwa wie folgt:
Anhalten des Threads:
// wir müssen den zugriff auf das Lockobjekt sperren lock(_oLock) { // hier halten wir den Thread an, bis der Zugriff wieder gegeben wird Monitor.Wait(_oLock); }
Fortsetzen des Threads:
lock(_oLock) { // hier erlauben wir die weiterarbeit des Threads Monitor.Pulse(_oLock); }
Könntest du auf C++ so angepasst übernehmen.
-
Guter Stil war das, was du da machst, noch nie.
Wie wärs, wenn du mal ein bischen über Multithreading liest:
http://www.albahari.com/threading/Da geht es zwar um C#, aber Texte für C++/CLI wirst du wohl kaum finden.
physici_errantes schrieb:
Welche Befehle ersetzen die beiden veralteten? Das heißt, wie mach ich es jetzt wieder richtig.
Man sollte die Steuerung von Threads explizit programmieren und ihnen nicht einfach den Saft abdrehen. Abort ist so, als wenn man sein Auto abwürgt, weil man nicht weiß, wie man den Motor abschaltet.
Du könntest z.B. einen Event verwenden, wie in der Fehlermeldung schon vorgeschlagen. Beispiele finden sich in dem verlinkten Text.
-
nn schrieb:
Guter Stil war das, was du da machst, noch nie.
Das weiß ich selber :), aber wie kommst du drauf? Ich habe mir C++ nicht ausgesucht, sondern musste es lernen, da die vorhandenen Bibliotheken alle in C waren und man statische Bibliotheken nur sehr schwer in C# einbinden kann. Auch das Thread::Abort nicht besonders elegant ist, weiß ich seit geraumer Zeit. Aber in diesem Thread läuft ein nicht linearer Fit, welcher u. U. sehr lange arbeitet, ohne das nennenswerte Fortschritte auf den ersten Blick erkennbar sind. Während der Berechnung kommt er auch nicht an irgendwelchen Haltepunkten vorbei, wo man ihn evtl. unterbrechen könnte. Er entspricht also eher einem alten Traktordiesel, den man auch abstellt, indem man ihn abwürgt. Daher erschien mir Abort die einfachste Möglichkeit, dem Wunsch des Nutzers nachzukommen.
Ich werd es mal mit der Monitor-Klasse versuchen.
-
Ich habe es jetzt mit der Monitor-Klasse probiert, aber das Resultat ist nicht wie gewünscht. Daher noch mal etwas genauer.
Ich habe zwei Klassen, das "Hauptprogramm" und eine für Mathematik. Aus dem Hauptprogramm möchte ich einen Thread erzeugen, welcher eine Funktion der Mathematik-Klasse abarbeitet. Wird zwischenzeitlich eine Test gedrückt, dann soll der Thread mit der Mathematik-Funktion angehalten werden bis ich ihn fortsetze oder abbreche.
Bisher funktioniert das mit:
Thread^ oThread = gcnew Thread( gcnew ThreadStart( &Mathematics::DoLevenberg )); //Set lowest priority oThread->Priority = Threading::ThreadPriority::Lowest; //Clear Message queue Application::DoEvents(); //Start Thread oThread->Start(); //Sleep 500 ms Thread::Sleep(500); //Loop for checking keyboard input while other thread is active while(oThread->IsAlive) { //KeyAvailable checks message queue for keypress //returns true if a key has been pressed if(Console::KeyAvailable) { //Suspend thread oThread->Suspend(); //DoStuff oThread->Resume(); } }
Da oThread aber eine andere Klasse ist, kann ich keine Lock-Anweisung verwenden. Oder kann ich die Lock-Variable irgendwie übergeben?
So in etwa:public ref class Main: { private: bool _locker; //lock-Variable public: void Main() { _locker = true; //Create new Thread Thread^ oThread = gcnew Thread( gcnew ThreadStart(&Mathematics::DoLevenberg(_locker)); //start Thread oThread->Start while(oThread->IsAlive) { if(Console::KeyAvaiable) { Monitor::Enter(_locker); //DoStuff Monitor::Exit(_locker); } } } }; public ref class Mathematic: //in anderer Datei { private: bool _locker; public static void DoLevenberg(bool lock) { _locker = lock; while(_locker) { //Do Levenberg-Algorithm } } };
Das Problem ist, dass ich nicht den Levenberg-Algorithmus anhalten kann, da dieser in einer externen Bibliothek sitzt. Ich muss also den ganzen Thread als solchen anhalten. Daher weiß ich nicht, ob diese while-Schleife das macht. Ich dachte mir das jetzt so, dass wenn ich im "Main"-Thread die _locker-Variable sperre, dass dann der andere Thread nicht mehr weiter machen kann, da die while-Schleife keinen Zugriff auf diese _locker-Variable bekommt.
Stimmt das? Könnt ihr mir helfen?
Danke
physici
-
Habe das Problem gelöst *freu*
Es funktioniert doch mit der Monitor-Klasse. Ich muss nur das richtige Objekt blockieren. In diesem Fall ist es der Ausgabe-Stream der entsprechenden Konsole, in welcher der oThread auch reinschreibt.
Thread^ oThread = gcnew Thread( gcnew ThreadStart( &Mathematics::DoLevenberg )); //Set lowest priority oThread->Priority = Threading::ThreadPriority::Lowest; //Clear Message queue Application::DoEvents(); //Start Thread oThread->Start(); //Sleep 500 ms Thread::Sleep(500); //Loop for checking keyboard input while other thread is active while(oThread->IsAlive) { //KeyAvailable checks message queue for keypress //returns true if a key has been pressed if(Console::KeyAvailable) { //Suspend thread Monitor::Enter(Console::Out); //DoStuff Monitor::Exit(Console::Out); } }