C++ Multithreading + Klassen

01/13/2010 20:08 Shadow992#1
Mein Problem ist es , dass ich eine Klasse habe (nehmen wir als Beispiel Auto)
und eine Funktion (Beispiel : BremswegBerechnen) habe , die aber in einem extra Thread laufen soll . Also so in etwa :

Code:
.
.
.
int main()
{
CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)BMW.BremswegBerechnen, 0, 0, 0);
}
.
.
.
Das das so nicht funktioniert , habe ich auch schon festgestellt , was ich leider nicht machen kann ist folgendes :

Code:
int main()
{
CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)test, 0, 0, 0);
}

void test()
{
BMW.BremswegBerechnen;
}
Das funktioniert aufgrund meiner momentanen Situation nicht
(Ich will den Code ja nicht für die Klasse Auto haben , sondern für eine andere bereits vorhandene Klasse , würde ich aber mein Code hier posten , würde das den Rahmen sprengen , da er recht umfangreich ist und sehr viele verwirren wird , weil darin Funktionen enthalten sind , die eig. nur sehr wenige kennen dürften)

Ich habe es bereits mit der "Klasse" Boost von dieser Seite probiert :
[Only registered and activated users can see links. Click Here To Register...]
Leider kommen bei meinem Compiler ein paar Errors (ich benutze wxDev-C++ , mit VC++ habe ich die Klasse noch nicht probiert , da ich eigentlich nur sehr ungerne auf VC++ umsteigen möchte , vorallem weil mir die wxDev-C++ so sehr ans Herz gewachsen ist)

Hier mal die Errors :
Code:
Compiler: Default GCC compiler
Building Makefile: "C:\Dokumente und Einstellungen\Benutzername\Desktop\Neuer Ordner\Makefile.win"
Finding dependencies for file: C:\Dokumente und Einstellungen\Benutzername\Desktop\Neuer Ordner\main.cpp
Führt  make... aus
make.exe -f "C:\Dokumente und Einstellungen\Benutzername\Desktop\Neuer Ordner\Makefile.win" all
g++.exe -c main.cpp -o main.o -I"C:/Programme/Dev-Cpp/lib/gcc/mingw32/3.4.5/include"  -I"C:/Programme/Dev-Cpp/include/c++/3.4.5/backward"  -I"C:/Programme/Dev-Cpp/include/c++/3.4.5/mingw32"  -I"C:/Programme/Dev-Cpp/include/c++/3.4.5"  -I"C:/Programme/Dev-Cpp/include"  -I"C:/Programme/Dev-Cpp/"  -I"C:/Programme/Dev-Cpp/include/common/wx/msw"  -I"C:/Programme/Dev-Cpp/include/common/wx/generic"  -I"C:/Programme/Dev-Cpp/include/common/wx/html"  -I"C:/Programme/Dev-Cpp/include/common/wx/protocol"  -I"C:/Programme/Dev-Cpp/include/common/wx/xml"  -I"C:/Programme/Dev-Cpp/include/common/wx/xrc"  -I"C:/Programme/Dev-Cpp/include/common/wx"  -I"C:/Programme/Dev-Cpp/include/common"  -I"C:/Dev-Cpp/include"   

In file included from C:/Dev-Cpp/include/boost/thread/future.hpp:12,
                 from C:/Dev-Cpp/include/boost/thread.hpp:24,
                 from main.cpp:1:
C:/Dev-Cpp/include/boost/exception_ptr.hpp:43: error: looser throw specifier for `virtual boost::exception_ptr::~exception_ptr()'
C:/Dev-Cpp/include/boost/exception/detail/exception_ptr_base.hpp:27: error:   overriding `virtual boost::exception_detail::exception_ptr_base::~exception_ptr_base() throw ()'

make.exe: *** [main.o] Error 1

Ausführung beendet
}
und der dazugehörige Code (Ist ein beispiel COde , also sollte er funktionieren)
Code:
#include <boost/thread.hpp> 
#include <iostream> 

void wait(int seconds) 
{ 
  boost::this_thread::sleep(boost::posix_time::seconds(seconds)); 
} 

void thread() 
{ 
  for (int i = 0; i < 5; ++i) 
  { 
    wait(1); 
    std::cout << i << std::endl; 
  } 
} 

int main() 
{ 
  boost::thread t(thread); 
  t.join(); 
}
Die Verzeichnisse sind ganz sicher richtig gesetzt und es sind auch ganz sicher alle Datein vorhanden . Habe auch schon Neuinstallation von wxDev-C++ gemacht und es kamen die selben Errors , ich hoffe mir kann jemand helfen oder eine Alternative zu dieser Klasse geben ...

Danke schonmal im vorraus
01/14/2010 12:19 kennyo#2
Deine erste Methode geht so:

PHP Code:
DWORD WINAPI ThreadFunc(LPVOID obj){
    
BMWobjekt = (BMW *)obj;
           
BMW->BremswegBerechnen("argument");
    return 
0;
}

auto BMW("argument""999");
auto.starteMotor();
auto.fahren(100"km/h");
HANDLE thread CreateThread(NULL0ThreadFunc, (LPVOID)&auto0NULL); 
Du musst einfach eine Referenz des Objektes an die Threadfunction übergeben, und daraus dann zurückcasten.
Es geht allerdings nicht, direkt in der Klasse eine Methode an den Thread zu übergeben (zumindest nicht mit CreateThread, sondern nur mit externen Klassen), sondern du müsstest eine Globale Funktion haben, und diese dann wie oben aus der Klasse heraus benutzen.

Aber erklär doch mal genauer was du machen willst, vllt. kann man es anders lösen.
01/14/2010 16:31 Shadow992#3
Quote:
Originally Posted by kennyo View Post
Deine erste Methode geht so:

PHP Code:
DWORD WINAPI ThreadFunc(LPVOID obj){
    
BMWobjekt = (BMW *)obj;
           
BMW->BremswegBerechnen("argument");
    return 
0;
}

auto BMW("argument""999");
auto.starteMotor();
auto.fahren(100"km/h");
HANDLE thread CreateThread(NULL0ThreadFunc, (LPVOID)&auto0NULL); 
Du musst einfach eine Referenz des Objektes an die Threadfunction übergeben, und daraus dann zurückcasten.
Es geht allerdings nicht, direkt in der Klasse eine Methode an den Thread zu übergeben (zumindest nicht mit CreateThread, sondern nur mit externen Klassen), sondern du müsstest eine Globale Funktion haben, und diese dann wie oben aus der Klasse heraus benutzen.

Aber erklär doch mal genauer was du machen willst, vllt. kann man es anders lösen.
Danke für deine Antwort .
Ich wollte eine Art Syntax Highlighting machen ...
Ich habe jetzt mal ein bisschen mit deinem Code rumprobiert , aber habe nicht wirklich eine Lösung gefunden ...

Bei mir ist das etwas komplizierter , als du es dargestellt hast ... Ich kopier mal das wichtigste ...
PHP Code:
AutoITEditDlg::AutoITEditDlg(wxWindow *parentwxWindowID id, const wxString &title, const wxPoint &position, const wxSizesizelong style)
wxDialog(parentidtitlepositionsizestyle


{
    
CreateGUIControls();      
    
HANDLE thread CreateThread(NULL0Highlight, (LPVOID)&WxRichTextCtrl10NULL);

  
}

void AutoITEditDlg::CreateGUIControls()
{
//Hier wird natürlich noch mehr gemacht , aber das brauchst du denke ich //mal nicht ...
    
WxRichTextCtrl1 = new wxRichTextCtrl(thisID_WXRICHTEXTCTRL1wxT(""), wxPoint(00), wxSize(797405), wxTAB_TRAVERSAL wxWANTS_CHARS wxVSCROLL wxHSCROLL wxNO_BORDER wxRE_MULTILINEwxDefaultValidatorwxT("WxRichTextCtrl1"));

}

void AutoITEditDlg::Highlight(LPVOID WxRichTextCtrl1)
{
//...
WxRichTextCtrl1->GetValue()
//...

So hatte ich es jetzt mal probiert ...
Es funktioniert aber nicht ...
Mit Klassen hatte ich bisher eigentlich keine Probleme ...

Danke schonmal im vorraus
01/14/2010 17:58 MrSm!th#4
Quote:
Originally Posted by Shadow992 View Post
Code:
int main()
{
CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)test, 0, 0, 0);
}

void test()
{
BMW.BremswegBerechnen;
}
nur mal nebenbei:

1. muss text() auch vor CreateThread definiert sein (also Prototyp reicht)
2. text() muss DWORD zurückgeben und die Calling Convetion WINAPI haben ;)
01/15/2010 19:04 kennyo#5
Mir fällt grad auf, dass ich was falsch gemacht habe.

statt

PHP Code:
DWORD WINAPI ThreadFunc(LPVOID obj){ 
    
BMWobjekt = (BMW *)obj
           
BMW->BremswegBerechnen("argument"); 
    return 
0


auto BMW("argument""999"); 
auto.starteMotor(); 
auto.fahren(100"km/h"); 
HANDLE thread CreateThread(NULL0ThreadFunc, (LPVOID)&auto0NULL); 
muss es

PHP Code:
DWORD WINAPI ThreadFunc(LPVOID obj){ 
    
BMWobjekt = (BMW *)obj
           
objekt->BremswegBerechnen("argument"); 
    return 
0


auto BMW("argument""999"); 
auto.starteMotor(); 
auto.fahren(100"km/h"); 
HANDLE thread CreateThread(NULL0ThreadFunc, (LPVOID)&auto0NULL); 
heissen.

Das funktioniert auf jedenfall, so steht es in einem meiner Programme.

Und zeig mir mal den Code der bei dir mit //... auskommentiert ist, denn da ist grade der Knackpunkt mit dem zurückcasten. Halte dich einfach an mein Beispiel. BMW ist da übrigens der Klassenname, was im nachhinein ein wenig verwirrend sein kann.
01/15/2010 20:39 Shadow992#6
Ich habe es jetzt mal so probiert :
PHP Code:
 
#include <stdio.h>
#include <string>
#include "AutoITEditDlg.h"
#include <windows.h>
#include<wx/timer.h>

            
size_t sizef;
            
size_t len ;
            
int high=;
            
int high2=;
            
wxString stri;
            
wxString st;
            
wxString stringtofind;

DWORD WINAPI ThreadFunc(LPVOID obj)

 
wxRichTextCtrlWxRichTextCtrl1 = (wxRichTextCtrl *)obj
   while (
1==1)
 {
//Sleep(3000);
if (WxRichTextCtrl1->GetValue()!=stri  )
  {
if ( 
high==1)
   {
      
sizet=0;    
      
len 5;
      
stringtofind "Func ";

      
stri=WxRichTextCtrl1->GetValue();
      if(
sizef=stri.find (stringtofind,sizet) ==wxNOT_FOUNDstringtofind=stringtofind.Lower() ; 
      if(
sizef=stri.find (stringtofind,sizet) ==wxNOT_FOUNDstringtofind=stringtofind.Upper() ;         
      while(
stri.find (stringtofind,sizet) !=wxNOT_FOUND)
     {
        
sizef stri.find (stringtofind,sizet);
        
WxRichTextCtrl1->EndTextColour();
        
attr.SetTextColour(wxColour(00255));
        
WxRichTextCtrl1->SetStyle(sizef,sizef+len,attr);
        
sizet=sizef+len ;
        
WxRichTextCtrl1->BeginTextColour(wxColour(000));
     }
   }
  }
 }
}
AutoITEditDlg::AutoITEditDlg(wxWindow *parentwxWindowID id, const wxString &title, const wxPoint &position, const wxSizesizelong style)
wxDialog(parentidtitlepositionsizestyle


{
    
CreateGUIControls();      
    
WxRichTextCtrl1->Clear();    
    
WxRichTextCtrl1->BeginFontSize(8);
    
//WxRichTextCtrl1->BeginBold();
    //WxTimer1->Start(6000);
    
HANDLE thread CreateThread(NULL0ThreadFunc, (LPVOID)&WxRichTextCtrl10NULL); 

    

}

AutoITEditDlg::~AutoITEditDlg()
{


void AutoITEditDlg::CreateGUIControls()
{
    
//Do not add custom code between
    //GUI Items Creation Start and GUI Items Creation End.
    //wxDev-C++ designer will remove them.
    //Add the custom code before or after the blocks
    ////GUI Items Creation Start

    
WxTimer1 = new wxTimer();
    
WxTimer1->SetOwner(thisID_WXTIMER1);

    
WxButton5 = new wxButton(thisID_WXBUTTON5wxT("Number Highlighting On"), wxPoint(507449), wxSize(14328), 0wxDefaultValidatorwxT("WxButton5"));

    
WxButton1 = new wxButton(thisID_WXBUTTON1wxT("Functions Highlighting On"), wxPoint(506416), wxSize(14429), 0wxDefaultValidatorwxT("WxButton1"));

    
WxStaticText1 = new wxStaticText(thisID_WXSTATICTEXT1wxT("Ready"), wxPoint(59468), wxDefaultSize0wxT("WxStaticText1"));

    
WxButton4 = new wxButton(thisID_WXBUTTON4wxT("Look For Errors"), wxPoint(654415), wxSize(14064), 0wxDefaultValidatorwxT("WxButton4"));

    
WxButton3 = new wxButton(thisID_WXBUTTON3wxT("Read"), wxPoint(155413), wxSize(14164), 0wxDefaultValidatorwxT("WxButton3"));

    
WxButton2 = new wxButton(thisID_WXBUTTON2wxT("Write"), wxPoint(4411), wxSize(14854), 0wxDefaultValidatorwxT("WxButton2"));

    
WxRichTextCtrl1 = new wxRichTextCtrl(thisID_WXRICHTEXTCTRL1wxT(""), wxPoint(00), wxSize(797405), wxTAB_TRAVERSAL wxWANTS_CHARS wxVSCROLL wxHSCROLL wxNO_BORDER wxRE_MULTILINEwxDefaultValidatorwxT("WxRichTextCtrl1"));
    
WxRichTextCtrl1->SetMaxLength(0);
    
WxRichTextCtrl1->AppendText(wxT("WxRichTextCtrl1"));
    
WxRichTextCtrl1->SetFocus();
    
WxRichTextCtrl1->SetInsertionPointEnd();

    
SetTitle(wxT("AutoITEdit"));
    
SetIcon(wxNullIcon);
    
SetSize(8,8,804,523);
    
Center();
    
    
////GUI Items Creation End

Es funktioniert auch soweit , dass ich den Thread erstellen kann und er wird auch gestartet , aber sobald die erste Funktion kommt , für die das Objekt gebraucht wird , beendet sich das Programm ohne irgendwelche Errors oder ähnliches zu hinterlassen .

Edit :
Das ist nicht der komplette Code , aber wenn ich den kompletten Code poste , würde das in Unübersichtlichkeit enden und in Funktionen , die dir nicht bekannt sind
(auser du benutzt wxDevC++).
01/15/2010 23:04 kennyo#7
Quote:
Originally Posted by Shadow992 View Post
Ich habe es jetzt mal so probiert :
PHP Code:
 
#include <stdio.h>
#include <string>
#include "AutoITEditDlg.h"
#include <windows.h>
#include<wx/timer.h>

            
size_t sizef;
            
size_t len ;
            
int high=;
            
int high2=;
            
wxString stri;
            
wxString st;
            
wxString stringtofind;

DWORD WINAPI ThreadFunc(LPVOID obj)

 
wxRichTextCtrlWxRichTextCtrl1 = (wxRichTextCtrl *)obj
   while (
1==1)
 {
//Sleep(3000);
if (WxRichTextCtrl1->GetValue()!=stri  )
  {
if ( 
high==1)
   {
      
sizet=0;    
      
len 5;
      
stringtofind "Func ";

      
stri=WxRichTextCtrl1->GetValue();
      if(
sizef=stri.find (stringtofind,sizet) ==wxNOT_FOUNDstringtofind=stringtofind.Lower() ; 
      if(
sizef=stri.find (stringtofind,sizet) ==wxNOT_FOUNDstringtofind=stringtofind.Upper() ;         
      while(
stri.find (stringtofind,sizet) !=wxNOT_FOUND)
     {
        
sizef stri.find (stringtofind,sizet);
        
WxRichTextCtrl1->EndTextColour();
        
attr.SetTextColour(wxColour(00255));
        
WxRichTextCtrl1->SetStyle(sizef,sizef+len,attr);
        
sizet=sizef+len ;
        
WxRichTextCtrl1->BeginTextColour(wxColour(000));
     }
   }
  }
 }
}
AutoITEditDlg::AutoITEditDlg(wxWindow *parentwxWindowID id, const wxString &title, const wxPoint &position, const wxSizesizelong style)
wxDialog(parentidtitlepositionsizestyle


{
    
CreateGUIControls();      
    
WxRichTextCtrl1->Clear();    
    
WxRichTextCtrl1->BeginFontSize(8);
    
//WxRichTextCtrl1->BeginBold();
    //WxTimer1->Start(6000);
    
HANDLE thread CreateThread(NULL0ThreadFunc, (LPVOID)&WxRichTextCtrl10NULL); 

    

}

AutoITEditDlg::~AutoITEditDlg()
{


void AutoITEditDlg::CreateGUIControls()
{
    
//Do not add custom code between
    //GUI Items Creation Start and GUI Items Creation End.
    //wxDev-C++ designer will remove them.
    //Add the custom code before or after the blocks
    ////GUI Items Creation Start

    
WxTimer1 = new wxTimer();
    
WxTimer1->SetOwner(thisID_WXTIMER1);

    
WxButton5 = new wxButton(thisID_WXBUTTON5wxT("Number Highlighting On"), wxPoint(507449), wxSize(14328), 0wxDefaultValidatorwxT("WxButton5"));

    
WxButton1 = new wxButton(thisID_WXBUTTON1wxT("Functions Highlighting On"), wxPoint(506416), wxSize(14429), 0wxDefaultValidatorwxT("WxButton1"));

    
WxStaticText1 = new wxStaticText(thisID_WXSTATICTEXT1wxT("Ready"), wxPoint(59468), wxDefaultSize0wxT("WxStaticText1"));

    
WxButton4 = new wxButton(thisID_WXBUTTON4wxT("Look For Errors"), wxPoint(654415), wxSize(14064), 0wxDefaultValidatorwxT("WxButton4"));

    
WxButton3 = new wxButton(thisID_WXBUTTON3wxT("Read"), wxPoint(155413), wxSize(14164), 0wxDefaultValidatorwxT("WxButton3"));

    
WxButton2 = new wxButton(thisID_WXBUTTON2wxT("Write"), wxPoint(4411), wxSize(14854), 0wxDefaultValidatorwxT("WxButton2"));

    
WxRichTextCtrl1 = new wxRichTextCtrl(thisID_WXRICHTEXTCTRL1wxT(""), wxPoint(00), wxSize(797405), wxTAB_TRAVERSAL wxWANTS_CHARS wxVSCROLL wxHSCROLL wxNO_BORDER wxRE_MULTILINEwxDefaultValidatorwxT("WxRichTextCtrl1"));
    
WxRichTextCtrl1->SetMaxLength(0);
    
WxRichTextCtrl1->AppendText(wxT("WxRichTextCtrl1"));
    
WxRichTextCtrl1->SetFocus();
    
WxRichTextCtrl1->SetInsertionPointEnd();

    
SetTitle(wxT("AutoITEdit"));
    
SetIcon(wxNullIcon);
    
SetSize(8,8,804,523);
    
Center();
    
    
////GUI Items Creation End

Es funktioniert auch soweit , dass ich den Thread erstellen kann und er wird auch gestartet , aber sobald die erste Funktion kommt , für die das Objekt gebraucht wird , beendet sich das Programm ohne irgendwelche Errors oder ähnliches zu hinterlassen .

Edit :
Das ist nicht der komplette Code , aber wenn ich den kompletten Code poste , würde das in Unübersichtlichkeit enden und in Funktionen , die dir nicht bekannt sind
(auser du benutzt wxDevC++).
Dann wird der Thread wohl nicht richtig gestartet. Überprüf einfach mal ob das handle (thread) gültig ist, und falls nicht, lass dir mit [Only registered and activated users can see links. Click Here To Register...] den Fehlercode ausgeben.
01/16/2010 16:27 termi#8
Ich habe den Thread zwar nun nur kurz überflogen aber was ich noch gerne bemerken würde zu deinem Test-Programm (.. main() { CreateThread(...); return;})
wenn du den Thread in diesem Programm erzeugst, endet das Programm bevor der Thread möglicherweise ausgeführt wurde. Der Thread ist Teil deines Prozesses und der Prozess endet nach main(). Ein WaitForSingleObject(handle) sollte es da tun.
01/16/2010 16:51 Shadow992#9
Quote:
Originally Posted by termi View Post
Ich habe den Thread zwar nun nur kurz überflogen aber was ich noch gerne bemerken würde zu deinem Test-Programm (.. main() { CreateThread(...); return;})
wenn du den Thread in diesem Programm erzeugst, endet das Programm bevor der Thread möglicherweise ausgeführt wurde. Der Thread ist Teil deines Prozesses und der Prozess endet nach main(). Ein WaitForSingleObject(handle) sollte es da tun.
Ok danke für die Antwort , aber das war mir klar , Ich wollte den Code nur sehr kurz halten ;)