INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

DLL mit Threads



Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!

02.04.2007, 16:42
Beitrag #1

Jason Offline
LVF-Grünschnabel
*


Beiträge: 18
Registriert seit: Mar 2007

8.2.1, 8.5
-
kA


Deutschland
DLL mit Threads
Hi alle miteinander!
Stehe momentan an ein Problem.

Ich versuche schon seit paar wochen eine DLL zuschreiben mit 2 Threads.
Ich habe mir schon eine Applikation geschrieben die funktioniert, allerdings hat es einfach nicht geklappt das in einer DLL zu giessen.

Ich erzeuge zwei Threads eine zum Lesen aus einer Pipe und ein zum schreiben.
Der Lese-Thread befindet sich in eine Endlos-Schleife, da jederzeit irgendwas in der Pipe drinne stehen kann.
Der Schreibe Thread wird mit Events schlafen gelegt und bei einen neuen Befehl wieder ausgeweckt (Endlos-Schleife).
Nun habe ich das Problem das ich unter LabVIEW kein neuen Befehl senden kann, da es sich aufhängt.
Es funktioniert nur einmal am Anfang.

Ich hoffe mir kann einer helfen. Vielleicht hat jemand ein einfaches Beispiel das unter LabVIEW 8.2 läuft.

<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>
_declspec(dllexport) void Communicator::Pipe_Comm(CString lpDLLName, CString lpMessageIn, CString *lpMessageOut)
{
threadinfo.m_Input = lpMessageIn;
threadinfo.m_Output = lpMessageOut;

if (ThreadFlag == FALSE)
{
/*Laden einer DLL und Zugriff auf die Funktion*/

if (!::CreatePipe(&hOutputRead, &hOutputWrite, NULL, 0))
{
MessageBox (NULL, "READ: Es ist eine Fehler beim Erstellen der Pipe aufgetreten!", "Fehler", MB_ICONERROR | MB_OK);
FreeLibrary(hModDLL);
}


hEvent_0 = CreateEvent(NULL, FALSE, FALSE, "Event_Thread0");
hEvent_1 = (NULL, FALSE, TRUE, "Event_Thread1");
hEvInput = CreateEvent(NULL, TRUE, FALSE, "Event_Input");
hEvReturn = CreateEvent(NULL, FALSE, FALSE, "Event_Return");

if (DisablePipe != TRUE)
{


unsigned threadId;
Thread1[0] = (HANDLE)_beginthreadex(NULL,
0,
PipeThread1,
reinterpret_cast<void*>(this), // PipeThread argument
0,//CREATE_SUSPENDED, &threadId);

Thread1[1] = (HANDLE)_beginthreadex(NULL,
0,
PipeThread2,
reinterpret_cast<void*>(this), // PipeThread argument
0, //CREATE_SUSPENDED, &threadId);

ThreadFlag = TRUE;

}

else if(ThreadFlag == TRUE)
{
SetEvent(hEvent_1);
}

//WaitForMultipleObjects(2,Thread1,0, );
WaitForSingleObject(hEvReturn,INFINITE);
//Sleep(3000);
}

else if(DisablePipe == TRUE)
{
MessageBox(NULL, "Kommunikation nicht möglich!nLaden der DLL erforderlich.", "Fehler", MB_ICONERROR | MB_OK);
}
//return ;

}


unsigned __stdcall Communicator::PipeThread2(LPVOID lpThreadParameter)
{
//Schreibe-thread
Communicator *thread_info = (Communicator*)lpThreadParameter;
HANDLE Thread2 = thread_info->Thread1[0];
HANDLE hEvent0 = thread_info->hEvent_0;
HANDLE hEvent1 = thread_info->hEvent_1;
HANDLE hEv_Input = thread_info->hEvInput;
HANDLE hEv_Return = thread_info->hEvReturn;

DWORD dwResult;

char* cmd;
long id;
CString compare = ""; //New insert

//MessageBox(NULL, "Ausgabe-Thread wird gestartet .....", "Ausgabe-Thread", MB_OK);

while(1)
{
//HANDLE hEvent0 = thread_info->hEvent_0;
// HANDLE hEvent1 = thread_info->hEvent_1;

dwResult = WaitForSingleObject(hEvent1 , INFINITE);
if (dwResult == WAIT_OBJECT_0)
{
// MessageBox(NULL, "Schreibe in Pipe", "Schreibe", MB_OK);
MessageBox(NULL, thread_info->threadinfo.m_Input, "InputData", MB_OK);
id = strtol(thread_info->threadinfo.m_Input, &cmd, 10);

if (compare != thread_info->threadinfo.m_Input)
{
/*Hier wird der Befehl gesendet*/
}
else { SetEvent(hEv_Return);}
}
Sleep(10);
//SetEvent(hEvent0);
}

delete thread_info;
return 0;
}


unsigned __stdcall Communicator::PipeThread1(LPVOID lpThreadParameter)
{

//Lese-Thread
Communicator *thread_info = (Communicator*)lpThreadParameter;
HANDLE Thread3 = thread_info->Thread1[1];
//HANDLE hEvent0 = thread_info->hEvent_0;
HANDLE hEvent1 = thread_info->hEvent_1;
HANDLE hEvIn[2];
hEvIn[0] = thread_info->hEvent_0;
hEvIn[1] = thread_info->hEvInput;
HANDLE m_readpipe = thread_info->hOutputRead;
HANDLE hEv_Return = thread_info->hEvReturn;
DWORD dwResult;

unsigned long n;
char buf[1024];
DWORD dwAvail;
CString Text;

MessageBox(NULL, "Lese-Thread wird gestartet .....", "Lese-Thread", MB_OK);

while(1)
{

//HANDLE hEvent0 = thread_info->hEvent_0;
//dwResult = WaitForSingleObject(hEvent0 , INFINITE);
dwResult = WAIT_OBJECT_0;//WaitForMultipleObjects(2,hEvIn,0, INFINITE);

if (dwResult == WAIT_OBJECT_0)
{
//MessageBox(NULL, "Lese aus Pipe", "Lesen", MB_OK);
dwAvail = 0;
while(1)
{
if (!::PeekNamedPipe(m_readpipe, NULL, 0, NULL, &dwAvail, NULL)) // error, the child process might ended
break;

if (!dwAvail)
{
// no data available, return
Sleep (10);
//SetEvent(hEvent1);
//ResetEvent(hEvIn[1]);
break;
}

::ReadFile(m_readpipe, buf,sizeof(buf), &n, NULL);

if (n > 0)
{
buf[n] = '';
Text = buf;
Text.Replace("n","rn");
//*thread_info->threadinfo.m_Output = Text;
MessageBox(NULL, Text, "Lesen", MB_OK);
SetEvent(hEv_Return);
}
SetEvent(hEvent1);
ResetEvent(hEvIn[1]);
Sleep(10);
}

}

else if (dwResult == WAIT_TIMEOUT)
{
break;
}
}

delete thread_info;
return 0;
}
</div>
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.04.2007, 17:06
Beitrag #2

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.692
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
DLL mit Threads
' schrieb:Nun habe ich das Problem das ich unter LabVIEW kein neuen Befehl senden kann, da es sich aufhängt.

So ganz hab ich deinen Sourcecode nicht verstanden.

Zum "Füttern" der Sendetask respektive des Sendethreads von LV aus musst du in LV ja einen DLL-Knoten programmieren. Dieser Knoten ruft dann eine Funktion innerhalb der DLL auf. Diesem Knoten werden Daten mitgegeben. Zuletzt wird der Knoten beendet !

Hab ich das jetzt richtig aus deinem Sourcecode herausgelesen: Die Funktion, die du von LV aus zum Schreiben aufrufst, hat eine Endloasschleife mit "while(1)" ?

Wenn dem so ist: Wie wird die Funktion beendet? Ohne dass die Funktion beendet wird, wird auch LV nicht weiterlaufen. Die Funktion MUSS beedendet werden, ansonsten bleibt LV am Knoten hängen (was übrigens auch jede andere Programmiersprache machen würde.

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.04.2007, 17:34
Beitrag #3

Jason Offline
LVF-Grünschnabel
*


Beiträge: 18
Registriert seit: Mar 2007

8.2.1, 8.5
-
kA


Deutschland
DLL mit Threads
' schrieb:So ganz hab ich deinen Sourcecode nicht verstanden.

Zum "Füttern" der Sendetask respektive des Sendethreads von LV aus musst du in LV ja einen DLL-Knoten programmieren. Dieser Knoten ruft dann eine Funktion innerhalb der DLL auf. Diesem Knoten werden Daten mitgegeben. Zuletzt wird der Knoten beendet !

Hab ich das jetzt richtig aus deinem Sourcecode herausgelesen: Die Funktion, die du von LV aus zum Schreiben aufrufst, hat eine Endloasschleife mit "while(1)" ?

Wenn dem so ist: Wie wird die Funktion beendet? Ohne dass die Funktion beendet wird, wird auch LV nicht weiterlaufen. Die Funktion MUSS beedendet werden, ansonsten bleibt LV am Knoten hängen (was übrigens auch jede andere Programmiersprache machen würde.

Aus LabVIEW rufe ich eine Funktion auf die Zwei Threads und eine Pipe erzeugen und die Werte an die Threads weitergibt

Die beiden Thread haben eine Endlosschleife. Das Problem ist bei mein Lese-Thread muss ich immer überprüfen ob was in der Pipe steht
Bei mein Schreibe-Thread muss nicht unbedningt eine Endlosschleife rein. Die Threads sollten nicht das Porblem sein, die laufen Parrallel.

Ich habe auch schon überlegt ob ich das nicht anderes mache. Das ich zwei Funktionen habe eine zum lesen und ein zum schreiben und die Lese-Funktion in eine While -Schleife unter LabVIEW Setzten, dann könnte ich unter LabVIEW die Schleife jederzeit abbrechen. Bloss dann müsste ich an den Schreib Thread ein Handle übergeben zum schreiben in die Pipe. Ist nur die Frage wie ich den Handle übergebe.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
02.04.2007, 20:24
Beitrag #4

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.692
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
DLL mit Threads
In deinem Falle kann ich nicht weiterhelfen. Hier fehlen mir Grundlagen.

' schrieb:Aus LabVIEW rufe ich eine Funktion auf die Zwei Threads und eine Pipe erzeugen und die Werte an die Threads weitergibt
Also doch so, wie es sein soll.

Zitat:die Lese-Funktion in eine While -Schleife unter LabVIEW Setzten, dann könnte ich unter LabVIEW die Schleife jederzeit abbrechen.
Sehr sinnvoll.
Ich gehe davon aus, dass der Parameter "CString *lpMessageOut" zur Lesetask gehört. Da bin ich aber erstmal skeptisch. Bist du sicher, dass das so passt?

Zitat:Bloss dann müsste ich an den Schreib Thread ein Handle übergeben zum schreiben in die Pipe. Ist nur die Frage wie ich den Handle übergebe.
Beim Starten zurückgaben als UInt32 und beim Schreiben hineingeben ebenfalls als UINT32.

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
19.04.2007, 18:04
Beitrag #5

Jason Offline
LVF-Grünschnabel
*


Beiträge: 18
Registriert seit: Mar 2007

8.2.1, 8.5
-
kA


Deutschland
DLL mit Threads
Ich habe es mittlerweile hinbekommen.

Nun habe ich ein neues Problem.
Wenn ich in meiner DLL die geladen DLL mit freelibrary() freigegeben möchte beendet sich LabVIEW komplett.

Kennt jemand dieses Phenomen und kann mir helfen?

Ausserdem wenn ich LabVIEW danach wieder starte, kommt es das die DLL, die in der DLL geladen wird, nicht mehr findet.
Ich muss in "Call Library Function Node" die DLL neu auswählen, erst dann funktioniert es wieder.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
20.04.2007, 10:07
Beitrag #6

IchSelbst Offline
LVF-Guru
*****


Beiträge: 3.692
Registriert seit: Feb 2005

11, 14, 15, 17, 18
-
DE

97437
Deutschland
DLL mit Threads
' schrieb:Wenn ich in meiner DLL die geladen DLL mit freelibrary() freigegeben möchte beendet sich LabVIEW komplett.
Ich tippe mal auf AV ganz unten. Und darauf, dass das mit dem Speichermanager von LV zusammenhängt. Von letzterem habe ich noch weniger Ahnung als von erstem.

Zitat:Ausserdem wenn ich LabVIEW danach wieder starte, kommt es das die DLL, die in der DLL geladen wird, nicht mehr findet.
Diese Satz ist grammatikalisch falsch, so dass nur erahnen kann, was du meinst. Soll das heißen: Du hast eine DLL, nämlich die, die du gepostet hast. In dieser DLL wird eine weitere DLL geladen, und zwar die, die freigegeben werden soll. Und genau diese DLL, die geladen und entladen wird, findet LV beim Wiederanlauf nicht.

:unsure:Wie soll LV wissen, wie die DLL heißt, wenn die erst zur Laufzeit geladen wird Unsure
:unsure:Greifst du von LV aus auf die in der DLL geladene DLL zu? Unsure

Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
20.04.2007, 18:00
Beitrag #7

Jason Offline
LVF-Grünschnabel
*


Beiträge: 18
Registriert seit: Mar 2007

8.2.1, 8.5
-
kA


Deutschland
DLL mit Threads
' schrieb:Ich tippe mal auf AV ganz unten. Und darauf, dass das mit dem Speichermanager von LV zusammenhängt. Von letzterem habe ich noch weniger Ahnung als von erstem.

Diese Satz ist grammatikalisch falsch, so dass nur erahnen kann, was du meinst. Soll das heißen: Du hast eine DLL, nämlich die, die du gepostet hast. In dieser DLL wird eine weitere DLL geladen, und zwar die, die freigegeben werden soll. Und genau diese DLL, die geladen und entladen wird, findet LV beim Wiederanlauf nicht.
Genau das habe ich eigentlich gemeint. Allerdings ist der gepostete Code nicht mehr aktuell da ich einiges geändert habe.

' schrieb::unsure:Wie soll LV wissen, wie die DLL heißt, wenn die erst zur Laufzeit geladen wird Unsure
:unsure:Greifst du von LV aus auf die in der DLL geladene DLL zu? Unsure

Von LabVIEW aus greife ich nicht auf die geladene DLL zu. Ich greif nur von DLL auf die andere DLL zu.

Wenn ich von LabVIEW aus auf einen Button klicke, wird in der DLL eine Funktion aufgerufen, die die DLL wieder freigeben soll.
Bei Aufruf der Funktion "freelibrary(HANDLE);" wird alles beendet, so dass ich auf den Desktop zurückkehre. Das ist mein anderes Problem.
Ich weiss nicht ob das ein negativer Nebeneffekt von freelibrary ist.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Antwort schreiben 


Gehe zu: