Q&A

  • Thread에 관한 질문 입니다.
이건 쓰레드를 생성한후에..스레드가 알아서 디비에 접속후 그에대한 내용을 조회하는



프로그램 인데.. 문제가 조금 있습니다.,..



간단하게...100~200개 정도는 금방 처리 되지만



엄청 많이 생성하면 쓰레드가 종료가 되지 않고 계속 남아 있습니다..

(아무래두 디비에 락이 걸려서 그런게 아닌가 싶습니다만..)



물론 프로그램을 강제 종료하면 정상적으로 없어지기는 하지만 이프로그램은 종료되면



않되거든여...





글구 디비를 쓰레드로 처리 하는겟에 관해 아시는 분좀 대답좀 해주세여...



어케하면 무리없이 디비에서 입력/수정/삭제를 무난하게 할수 있는지여...



글구 뮤텍스라는게 있던데 그게 뭐에여? 개념이 안서네여...



function ThreadLogIn(Ptr : Pointer) : LongInt; stdcall;

var ADO : TADOQuery;

Data : PMsgUserLogin;

r_MsgLogInInfo : TMsgLogInInfo;

begin

Data := PMsgUserLogin(Ptr);



CoInitialize(nil);

ADO := TADOQuery.Create(Application);

with ADO do

begin

Connection := Form1.ADOConnection;

Active := False;

SQL.Clear;

SQL.Add('SELECT * FROM PangMember WHERE ID = :USERID');

Parameters.ParamByName('USERID').Value := Data^.ID;

Active := True;



r_MsgLogInInfo.Command := MsgLogInInfo;

if (RecordCount > 0) and (Data^.PASS = Fields.FieldByName('PASSWORD').Asstring) then

r_MsgLogInInfo.ErrorNumber := 0



//맞는 경우

else if (RecordCount > 0) and (Data^.PASS <> Fields.FieldByName('PASSWORD').Asstring) then

r_MsgLogInInfo.ErrorNumber := 2



//비밀번호가 틀리는 경우

else

r_MsgLogInInfo.ErrorNumber := 1;



//아이디가 틀리는 경우

Free;

end;



Form1.DXPlay.SendMessage(Data^.MyDxPlayId, @r_MsgLogInInfo, Sizeof(TMsgLogInInfo));

Dispose(Data);

CoUnInitialize;

Result := 0;

end;







호출하는 부분 입니다..



New(LogInData);

LogInData^.ID := TMsgUserLogin(Data^).ID;

LogInData^.PASS := TMsgUserLogin(Data^).PASS;

LogInData^.MyDxPlayId := From.ID;

ThreadHandle := CreateThread(nil, 0, @ThreadLogIn, LogInData, 0, ThreadID);



1  COMMENTS
  • Profile
    김정 2000.10.12 07:17
    안녕하세요?

    고드름 김정입니다.



    DB를 어떤 걸 사용하시는지 모르겠습니다만,

    ADO로 접속하신걸로 봐서는 Transaction 처리가 되지 않는 DB를 사용하시는 것 같군요.



    DB 자체적으로 Lock 처리가 제대로 되지 않을 때에는

    접속하는 클라이언트를 동기화시켜 어느 정도 해결할 수 있습니다.



    접속할 때 동시에 접근을 막기 위함입니다.

    이럴때 말씀하신 Mutex 나 Semaphore 같은

    동기화 객체 (Synchronous Object)를 사용합니다. ^^;



    Mutex는 접근하는 자원이 1개일 때, 사용할때마다 해당 Mutex를 잡고 사용하는 것이며,

    Semaphore는 1개 이상의 자원일 때, 사용할때마다 남은 수를 카운트하며 사용합니다.



    이것은 OS가 제공하는 객체로 한번에 하나의 프로세스(쓰레드)만 잡을 수 있습니다.

    하지만 잡고 놓고 하는데 시간이 좀 걸립니다. (상대적이긴 하지만..)



    그래서 멀티쓰레드를 동기화할 때는 Critical Section(임계범위 정도..)를 사용합니다.

    Mutex와 같은 개념으로 사용하지만, 다른 프로세스에서는 볼 수 없습니다.



    따라서 문제의 경우,

    CriticalSection 을 잡아주고,

    접속해서 작업하시고,

    CriticalSection 을 풀어주시면 됩니다.



    그럼 Thread 내에서 CriticalSection 내에 있는 부분은 하나씩만 동작하며,

    이때 나머지 쓰레드들은 멈춰있게 됩니다. 그리고 다음으로 넘어가게 됩니다.



    자세한 것은 MSDN 을 참고하셔야 할 것입니다.

    불행인지 다행인지 델파이에 CriticalSection은 구현되어 있습니다.

    하지만 Mutex와 Semaphore는 없습니다. -.-



    참고하세요.

    그럼.



    김진호 wrote:

    > 이건 쓰레드를 생성한후에..스레드가 알아서 디비에 접속후 그에대한 내용을 조회하는

    >

    > 프로그램 인데.. 문제가 조금 있습니다.,..

    >

    > 간단하게...100~200개 정도는 금방 처리 되지만

    >

    > 엄청 많이 생성하면 쓰레드가 종료가 되지 않고 계속 남아 있습니다..

    > (아무래두 디비에 락이 걸려서 그런게 아닌가 싶습니다만..)

    >

    > 물론 프로그램을 강제 종료하면 정상적으로 없어지기는 하지만 이프로그램은 종료되면

    >

    > 않되거든여...

    >

    >

    > 글구 디비를 쓰레드로 처리 하는겟에 관해 아시는 분좀 대답좀 해주세여...

    >

    > 어케하면 무리없이 디비에서 입력/수정/삭제를 무난하게 할수 있는지여...

    >

    > 글구 뮤텍스라는게 있던데 그게 뭐에여? 개념이 안서네여...

    >

    > function ThreadLogIn(Ptr : Pointer) : LongInt; stdcall;

    > var ADO : TADOQuery;

    > Data : PMsgUserLogin;

    > r_MsgLogInInfo : TMsgLogInInfo;

    > begin

    > Data := PMsgUserLogin(Ptr);

    >

    > CoInitialize(nil);

    > ADO := TADOQuery.Create(Application);

    > with ADO do

    > begin

    > Connection := Form1.ADOConnection;

    > Active := False;

    > SQL.Clear;

    > SQL.Add('SELECT * FROM PangMember WHERE ID = :USERID');

    > Parameters.ParamByName('USERID').Value := Data^.ID;

    > Active := True;

    >

    > r_MsgLogInInfo.Command := MsgLogInInfo;

    > if (RecordCount > 0) and (Data^.PASS = Fields.FieldByName('PASSWORD').Asstring) then

    > r_MsgLogInInfo.ErrorNumber := 0

    >

    > //맞는 경우

    > else if (RecordCount > 0) and (Data^.PASS <> Fields.FieldByName('PASSWORD').Asstring) then

    > r_MsgLogInInfo.ErrorNumber := 2

    >

    > //비밀번호가 틀리는 경우

    > else

    > r_MsgLogInInfo.ErrorNumber := 1;

    >

    > //아이디가 틀리는 경우

    > Free;

    > end;

    >

    > Form1.DXPlay.SendMessage(Data^.MyDxPlayId, @r_MsgLogInInfo, Sizeof(TMsgLogInInfo));

    > Dispose(Data);

    > CoUnInitialize;

    > Result := 0;

    > end;

    >

    >

    >

    > 호출하는 부분 입니다..

    >

    > New(LogInData);

    > LogInData^.ID := TMsgUserLogin(Data^).ID;

    > LogInData^.PASS := TMsgUserLogin(Data^).PASS;

    > LogInData^.MyDxPlayId := From.ID;

    > ThreadHandle := CreateThread(nil, 0, @ThreadLogIn, LogInData, 0, ThreadID);

    >