Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



ukoncenie vlakno Vlakna

Seznam témat     Nová odpověď

Přihlásit se     Registrace     Zapomenuté heslo

Re: ukoncenie vlakno Vlakna

Autor: Jaroslav Šmíd

16:51:47 18.11.2010

Zdroják jsem nečetl, je prasácky zdormátovaný (používej značku code v hranatých závorkách), ale pokud to opravdu řešíš proměnnou, měl bys si dát bacha:

Kompilátor to může při optimalizaci optimalizovat tak, že proměnnou umístí v kódu vlákna do registru a v hlavním vlákně pak můžeš zapsat do paměti novou hodnotu, ale v druhém vlákně se registr nezmění - kompilátor nemá křišťálovou kouli a tak bys mu měl pomoci a proměnnou označit slůvkem volatile, aby ji nenechával v registrech, ale četl z paměti.

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Veronisoft777

13:01:19 10.11.2010

Dik uz som to oravil dal som tam premennu na zrusenie vlakna a uz to nepada:
if (!AfxSocketInit())
{
AfxMessageBox(_T("Failed to Initialize Sockets"), MB_OK | MB_ICONSTOP);
}


INT reping = BOX_NET_ERROR;
CStringA adress;
UINT Port, Method,IPv;

char addressstr[150];
adress = Box->IPAdress;
Port = Box->Port;
Method = Box->CheckMetod;
IPv = Box->IPv;
strcpy( addressstr, adress.GetBuffer( adress.GetLength() ) );
adress.ReleaseBuffer();

while( 1 )
{
reping = BOX_NET_ERROR;
//Neskor skontroloat pretecnie zasobniku
//wcstombs( adress, Box->IPAdress.GetBuffer(Box->IPAdress.GetLength()), Box->IPAdress.GetLength() + 1);
//Box->IPAdress.ReleaseBuffer();

if( Method == CHM_PING )
{
//reping = IP_NET_ERROR;
if( IPv == 0 )
{
reping = net.Ping4( addressstr );
}
if( IPv == 1 )
{
reping = net.Ping6( addressstr );
}
// reping = net.Ping4WS( adress.GetBuffer( adress.GetLength() ) );
}

if( Method == CHM_TCP_CONNECT )
{
//reping = IP_NET_ERROR;
//Sleep( 2000 );
if( IPv == 0 )
{
reping = net.TcpConnect( addressstr, Port );
}
if( IPv == 1 )
{
reping = net.TcpConnect6( addressstr, Port );

}
}
if( EndEvent )
{
if( net.hIcmpFile != INVALID_HANDLE_VALUE )
IcmpCloseHandle( net.hIcmpFile );

if( net.LoadMe != NULL )
FreeLibrary( net.LoadMe );
AfxEndThread( 1 );
}
if( Box != NULL )
::SendMessage( Box->hmWnd, WM_NET_BOX, (WPARAM)Box->NumBox,(LPARAM)reping );
if( EndEvent )
{
if( net.hIcmpFile != INVALID_HANDLE_VALUE )
IcmpCloseHandle( net.hIcmpFile );
if( net.LoadMe != NULL )
FreeLibrary( net.LoadMe );
AfxEndThread( 1 );
}
Sleep( netsetting.CheckTime*1000 );
if( EndEvent )
{
if( net.hIcmpFile != INVALID_HANDLE_VALUE )
IcmpCloseHandle( net.hIcmpFile );
if( net.LoadMe != NULL )
FreeLibrary( net.LoadMe );
AfxEndThread( 1 );
}
}

Citovat příspěvek

 

Re: ukoncenie vlakno Vlakna

Autor: guma

15:44:58 09.11.2010

Ještě trochu konstruktivnější příspěvek, než byl ten můj předešlý.
Můžeš použít funkci IcmpSendEcho2, která se umí chovat asynchronně. Ale opět platí to, co jsem napsal o čtení dokumentace, v popisu funkce IcmpSendEcho je to totiž taky napsané.

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Farao

12:48:50 09.11.2010

>> a vo vnutri vlakna sa mi to neda zrusit pretoze ak pouzijem funkciu IcmpSendEcho a ta ma time out 3000 ms potom nemozem cakat kym sa skonci.

Čekat musíš. Pokud nemůžeš, tak máš špatně navrženou aplikaci. Použití TerminateThread je až poslední řešení a po jejím použití není zaručen správný stav prostředků používaných vláknem.

Korektní algoritmus pro ukončení vlákna je:

1) nastavit příznak, že má vlákno skončit a čekat na jeho dokončení nebo rovnou pokračovat pokud pro funkčnost nevadí, že vlákno ještě může běžet

2) vlákno příznak detekuje, uklidí po sobě (tj. počká se na dokončení IcmpSendEcho, uvolní se dynamicky alokovaná paměť atd.) a ukončí se funkce vlákna

Citovat příspěvek

 

Re: ukoncenie vlakno Vlakna

Autor: guma

12:03:03 09.11.2010

To s tim iphlpapi nevím, ale může to klíďo být důsledek násilného sestřelení vlákna, protože v něm zrovna probíhá nějaká činnost, nebo třeba proto, že vlákno po sobě nemůže správně uklidit alokované prostředky. vlákno evidentně provádí funkce, do kterých nevidíš (resp. neznáš jejich zdroják) a nevíš tedy, co se stane, když uprostřed provádění sestřelíš vlákno, ve kterém běží. Co hůř, je jasné, že ony funkce určitě budou mít co dočinění s kernelem a komunikací s hardwarem (konkrétně síťovkou). V takovém případě je používání TerminateThread docela hazard.

To, že nemůžeš ukončit vlákno jinak než prostřednictvím TerminateThread, je důsledek chybného návrhu tvojí aplikace. Nečekej, že to bude fungovat správně, takový přístup může a taky bude způsobovat jen problémy.

Asi největší problém bych viděl v tom, že stejně jako statisíce jiných vývojářů nedokážeš přečíst a porozumět dokumentaci ke všemu co používáš, např. u popisu funkce TerminateThread na msdn je jasně uvedeno, že může způsobovat potíže a ještě je tam i příklad jaké (a zdaleka tam nejsou všechny).
Ale nedělej si z toho hlavu, dělá to každej druhej programátor a případné problémy, které tím vzniknou, pak svedou na Windows a Microsoft a jsou z obliga - to je totiž dnes ohromně moderní a každý tekovému argumentu bohužel věří.

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Veronisoft777

11:44:29 09.11.2010

Uz som na to prisiel ak pustim TerminateThread na IcmpSendEcho tak vyhodi vynimku neviete preco?
Nieco podibne tu uz mam ale to uz je na win 7 opravene
http://forum.builder.cz/read.php?23,3068979,3078864

#define MAX_BUF_SIZE 1024
UINT CIcmpSendEchoBugDlg::IcmpThraed(LPVOID arg)
{
HANDLE hIcmpFile;
char strHost[]="192.168.2.109";
DWORD dwRetVal = 0;
IPAddr ipaddr = INADDR_NONE;
char SendData[] = "IP Monitor";
char ReplyBuffer[MAX_BUF_SIZE + sizeof(ICMP_ECHO_REPLY) + 8];
DWORD ReplySize = 0;

ipaddr = inet_addr(strHost);
if( ipaddr == INADDR_NONE )
{
hostent* hp = gethostbyname(strHost);
if( hp )
{

memcpy(&ipaddr,hp->h_addr,hp->h_length);
}
else
return 0;
}
hIcmpFile = IcmpCreateFile();
if( hIcmpFile == INVALID_HANDLE_VALUE )
{
return 0;
}
ReplySize = MAX_BUF_SIZE + sizeof(ICMP_ECHO_REPLY) + 8;
while( 1 )
{
dwRetVal = IcmpSendEcho( hIcmpFile, ipaddr,(LPVOID) SendData, sizeof(SendData), NULL, ReplyBuffer, ReplySize, 3000 );
}
return 0;
}
void CIcmpSendEchoBugDlg::OnBnClickedButton1()
{
Thread = AfxBeginThread( IcmpThraed,(LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED );
Thread->m_bAutoDelete = false;
Thread->ResumeThread();
}


void CIcmpSendEchoBugDlg::OnBnClickedButton2()
{
Thread->SuspendThread();
TerminateThread( Thread->m_hThread, 0 );
delete Thread;
}

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Veronisoft777

9:58:58 09.11.2010

a vo vnutri vlakna sa mi to neda zrusit pretoze ak pouzijem funkciu IcmpSendEcho a ta ma time out 3000 ms potom nemozem cakat kym sa skonci. Musim akamzite zrusit vlakno na zaklade impulzu z vonku co je zmazanie Boxu aplikacie IP Monitor http://veronisoft.hostei.com/ (neviem ci sa aplikacia moze tu uverejnit ak nie nech tu linku moderator zmaze)

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Veronisoft777

9:25:49 09.11.2010

Chcem este dodat ze ak pouzijem TerminateThread na to vlakno
dostanem
IPHLPAPI.DLL!72f958be()
[Frames below may be incorrect and/or missing, no symbols loaded for IPHLPAPI.DLL]
winnsi.dll!72f81afb()
....
neviete preco?
Podobnu chybu som nasiel aj na tejto linke
http://www.rsdn.ru/forum/winapi/2961877.1.aspx

Citovat příspěvek

 

Re: ukoncenie vlakno Vlakna

Autor: guma

8:10:08 09.11.2010

Ale to je právě ta chyba. Snad není problém v té smyčce udělat něco jako.
[code]
exit = false;
while(!exit)
{
//kod
}
[/code]
a z druhýho vlákna pro ukončení
[code]
exit = true;
[/code]

Jen ještě upozornění, že takhle sdílená proměnná nemusí být to pravé, je třeba řádně rozmyslet, jak se bude používat a jestli není potřeba použít nějaký jiný prostředek, který je plně thread-safe (pozn. konkrétně v tom mém příkladu je to ok). Ale princip zůstává.

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Veronisoft777

19:15:54 08.11.2010

Musim ho ukoncit z vonku lebo tam mam nekonecnu slucku:
#include "stdafx.h"
#include "IP Monitor.h"
#include "NetThread.h"
#include "Net.h"
#include "define.h"
#include "struct.h"
#include

//#pragma comment(lib, "IPHLPAPI.lib")
// CNetThred
extern NETSETTING netsetting;
IMPLEMENT_DYNCREATE(CNetThread, CWinThread)

CNetThread::CNetThread()
{

}

CNetThread::~CNetThread()
{
// AfxMessageBox(_T("fsdf") );
//CCriticalSection cs;
//cs.Lock();
//if( net.hIcmpFile != INVALID_HANDLE_VALUE )
// IcmpCloseHandle( net.hIcmpFile );
//cs.Unlock();
//AfxMessageBox(_T("fsdf") );
//FreeLibraryAndExitThread( GetModuleHandle( _T("IPHLPAPI.dll") ), 0 );
//FreeLibrary( GetModuleHandle( _T("IPHLPAPI.dll") ) );
}

BOOL CNetThread::InitInstance()
{

if (!AfxSocketInit())
{
AfxMessageBox(_T("Failed to Initialize Sockets"), MB_OK | MB_ICONSTOP);
}


INT reping = BOX_NET_ERROR;
CStringA adress;
UINT Port, Method,IPv;

char addressstr[150];
adress = Box->IPAdress;
Port = Box->Port;
Method = Box->CheckMetod;
IPv = Box->IPv;
strcpy( addressstr, adress.GetBuffer( adress.GetLength() ) );
adress.ReleaseBuffer();

while( 1 )
{
reping = BOX_NET_ERROR;
//Neskor skontroloat pretecnie zasobniku
//wcstombs( adress, Box->IPAdress.GetBuffer(Box->IPAdress.GetLength()), Box->IPAdress.GetLength() + 1);
//Box->IPAdress.ReleaseBuffer();

if( Method == CHM_PING )
{
//reping = IP_NET_ERROR;
if( IPv == 0 )
{
reping = net.Ping4( addressstr );
}
if( IPv == 1 )
{
reping = net.Ping6( addressstr );
}
// reping = net.Ping4WS( adress.GetBuffer( adress.GetLength() ) );
}

if( Method == CHM_TCP_CONNECT )
{
//reping = IP_NET_ERROR;
//Sleep( 2000 );
if( IPv == 0 )
{
reping = net.TcpConnect( addressstr, Port );
}
if( IPv == 1 )
{
reping = net.TcpConnect6( addressstr, Port );

}
}
//AfxMessageBox( _T("") );
::SendMessage( Box->hmWnd, WM_NET_BOX, (WPARAM)Box->NumBox,(LPARAM)reping );
Sleep( netsetting.CheckTime*1000 );
}

return FALSE;
}
int CNetThread::ExitInstance()
{
return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(CNetThread, CWinThread)
END_MESSAGE_MAP()

Citovat příspěvek

 

Re: ukoncenie vlakno Vlakna

Autor: guma

17:53:07 08.11.2010

To vypadá jako nějaké MFC, tam se pokud vím vytvářejí vlákna jinak, má s tím co dočinění funkce AfxBeginThread, ale v tom přesně neporadím, MFC nedělám.
Ale obecně - vlákno by se nejsprávněji mělo ukončit samo, tzn. tak, že funkce vlákna skončí. To je čistý způsob a taky asi jediný zcela bezpečný. Samozřejmě api poskytuje funkci TerminateThread apod., kterou lze vlákno sestřelit i z jiného vlákna, ale to by se mělo používat jen v případech nouze, např. když se vlákno nějak někde zasekne.
Správně by to tedy mělo vypadat tak, že vlákno implementuje nějaký způsob, jak ho lze požádat o ukončení, a to pomocí prostředků pro mezivláknovou komunikaci (zprávy, sdílená proměnná apod.) Pokud ho chceš ukončit odjinud, tak ho prostřednictvím toho prostředku o ukončení požádáš a příp. můžeš počkat, než skončí. Tedy źádný TerminateThread nebo delete.

Citovat příspěvek

 

Re: ukoncenie Vlakna

Autor: Veronisoft777

13:26:49 08.11.2010

CNetThread je:
class CNetThread : public CWinThread
{
DECLARE_DYNCREATE(CNetThread)

public:
CNetThread(); // protected constructor used by dynamic creation
virtual ~CNetThread();

public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//INT BoxNum;
KBox *Box;
HWND m_hMainWnd;
CNet net;
//HANDLE *phIcmpFile;
protected:
DECLARE_MESSAGE_MAP()
};

Citovat příspěvek

 

Re: ukoncenie vlakno Vlakna

Autor: guma

13:02:38 08.11.2010

No nikdo zatím neodpovídá, tak se zeptám já: Co je za třídu CNetThread? To neznám.

Citovat příspěvek

 

Re: ukoncenie vlakna

Autor: Veronisoft777

12:07:12 08.11.2010

Pretoze ak pouzijem
NetThread->SuspendThread();
delete NetThread;
Vlakno sa mi v poriadku zrusi ale vo Windows Task Managet->Processes->Threads
sa mi nedecrementuje hodnota

A ak pouzijem
NetThread->SuspendThread();
TerminateThread( NetThread->m_hThread, 0 );
delete NetThread;
Vlakno sa mi v poriadku zrusi ale Windows Task Managet->Processes->Threads
sa mi decrementuje ich hodnota ale vyhodi mi vinimku asi IPHLPAPI.DLL exeption
co je asi vo vlakne funkcia Icmp6SendEcho2 "ktora sa neda uvolnit"?

Citovat příspěvek

 

ukoncenie vlakno Vlakna

Autor: Veronisoft777

16:47:47 06.11.2010

Mam vlakno ktore spustim
NetThread = new CNetThread();
this->NetThread->Box = this;
NetThread->CreateThread(CREATE_SUSPENDED);
NetThread->m_bAutoDelete = false; // Let me delete it.
NetThread->ResumeThread();

mozem ho zrusi( vmazat )cez

NetThread->SuspendThread();
delete NetThread;

alebo musim pouzit

NetThread->SuspendThread();
TerminateThread( NetThread->m_hThread, 0 );
delete NetThread;

Citovat příspěvek

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: