|
메인폼에 있는 놈들을 하위 스레드에서 사용하려면.. 반드시 Synchronize 를 사용하셔야 합니다.
기본적으로 Synchronize 사용이 하나도 없는 걸로봐서 5개 스레드가 움직일때 문제가 없는것이 더 이상합니다.
요행이 테스트에서 충돌이 없다고 해도 매우 위험한 처리 방법입니다.
Synchronize(유저정의함수명); 이렇게 하면 됩니다.
유저정의함수는 반드시 리턴값도없고, 전달 인수도 사용할 수 없습니다. 따라서 전역변수를 사용하여 미리 값을주고
Synchronize 시에 유저정의 함수에서 전역변수를 이용하여 값을 주거나 받으시면 됩니다. 또한 메인폼에 있는 모든
놈들을 마음껏 사용하셔도 됩니다.
메인폼에서 버튼을 클릭시에 하위스레드가 사용하는 시리얼 포트를 사용하려면
1. 전역변수에 사용예약을 알리고
2. 현재 사용중인 스레드가 하는일을 정상적으로 완료하여 끝나도록 합니다.
3. 다음 스레드는 사용예약을 알리는 값을 먼저 읽어서 사용여부를 확인후 시리얼 포트를 사용하도록 합니다.
4. 현재 사용중인 스레드가 일을 마치면 메인프로그램이 시리얼포트를 사용합니다.
5. 메인프로그램이 사용을 마치면 사용예약 값을 해제하여 다음 스레드가 시리얼 포트를 사용 하도록 합니다.
이와같은 로직으로 처리 하시면 될듯 합니다..
worldfip 님이 쓰신 글 :
: 일단 세마포어를 사용했습니다.
: 5개의 스레드가 같은 포트의 232 통신을 사용합니다.
: 통신방법은 질문을 던지고 응답을 받아야 합니다. 이게 1사이클입니다.
: 그래서 Semaphore = CreateSemaphore (NULL, 1, 1, NULL); 요렇게 했습니다.
: 몇개의 스레드가 동시 접근되면 주고-받는 사이클에서 miss가 발생되기 때문에 1개의 스레드만 접근하게끔...
:
: 또한 메인폼에서 버튼을 클릭했을때 같은 포트의 232 통신을 시도 합니다.
: 그런데 5개의 스레드가 운영될때는 서로간에 충돌없이 아주 잘 운영되었는데
: 메인폼에서 버튼을 눌러 통신을 시도하게 되면 프로그램이 Deadlock 되어 버립니다.
: 도저히 원인을 모르겠네요.
:
: Semaphore, CriticalSection, Event 모두 시도해 보았는데 똑같은 현상을 보이네요. 이거 해결책 없을까요?
:
:
:
:
: 메인 프로그램입니다.
: //---------------------------------------------------------------------------
:
: #include <vcl.h>
: #include <SyncObjs.hpp>
: #pragma hdrstop
:
: #include "Unit1.h"
: //---------------------------------------------------------------------------
: #pragma package(smart_init)
: #pragma resource "*.dfm"
: TForm1 *Form1;
: HANDLE Semaphore;
: //---------------------------------------------------------------------------
: __fastcall TForm1::TForm1(TComponent* Owner)
: : TForm(Owner)
: {
: m_RS232.Setup(1, 19200, 8, 1, "None");
: m_RS232.Connect();
: }
: //---------------------------------------------------------------------------
:
: void __fastcall TForm1::FormShow(TObject *Sender)
: {
: Semaphore = CreateSemaphore (NULL, 1, 1, NULL);
:
: m_pThread[0] = new TTest(true);
: m_pThread[0]->m_pEditFail = Edit2;
: m_pThread[0]->m_pEditSucc = Edit7;
: m_pThread[0]->m_iThreadNum = 1;
: m_pThread[1] = new TTest(true);
: m_pThread[1]->m_pEditFail = Edit3;
: m_pThread[1]->m_pEditSucc = Edit8;
: m_pThread[1]->m_iThreadNum = 2;
: m_pThread[2] = new TTest(true);
: m_pThread[2]->m_pEditFail = Edit4;
: m_pThread[2]->m_pEditSucc = Edit9;
: m_pThread[2]->m_iThreadNum = 3;
: m_pThread[3] = new TTest(true);
: m_pThread[3]->m_pEditFail = Edit5;
: m_pThread[3]->m_pEditSucc = Edit10;
: m_pThread[3]->m_iThreadNum = 4;
: m_pThread[4] = new TTest(true);
: m_pThread[4]->m_pEditFail = Edit6;
: m_pThread[4]->m_pEditSucc = Edit11;
: m_pThread[4]->m_iThreadNum = 5;
:
: m_pThread[0]->Resume();
: m_pThread[1]->Resume();
: m_pThread[2]->Resume();
: m_pThread[3]->Resume();
: m_pThread[4]->Resume();
: }
: //---------------------------------------------------------------------------
:
:
: __fastcall TForm1::~TForm1()
: {
: m_pThread[0]->Terminate();
: WaitForSingleObject(m_pThread[0], INFINITE);
: m_pThread[1]->Terminate();
: WaitForSingleObject(m_pThread[1], INFINITE);
: m_pThread[2]->Terminate();
: WaitForSingleObject(m_pThread[2], INFINITE);
: m_pThread[3]->Terminate();
: WaitForSingleObject(m_pThread[3], INFINITE);
: m_pThread[4]->Terminate();
: WaitForSingleObject(m_pThread[4], INFINITE);
: CloseHandle (Semaphore);
: }
:
: void __fastcall TForm1::Button1Click(TObject *Sender)
: {
: AnsiString strRcv;
:
: Button1->Enabled = false;
:
: WaitForSingleObject(Semaphore, INFINITE);
:
: strRcv = m_RS232.SendString("Main\r\n", "\r\n", "");
: if (strRcv.AnsiCompare("\r\n") == 0)
: {
: int i = Edit1->Text.ToInt ();
: Edit1->Text = IntToStr (++i);
: }
:
: ReleaseSemaphore (Semaphore, 1, NULL);
:
: Button1->Enabled = true;
: }
: //---------------------------------------------------------------------------
:
:
:
:
:
:
: 스레드 프로그램입니다.
:
:
: //---------------------------------------------------------------------------
:
: #include <vcl.h>
: #include <SyncObjs.hpp>
: #pragma hdrstop
:
: #include "Unit2.h"
: #include "Unit1.h"
: #pragma package(smart_init)
: //---------------------------------------------------------------------------
:
: // Important: Methods and properties of objects in VCL can only be
: // used in a method called using Synchronize, for example:
: //
: // Synchronize(UpdateCaption);
: //
: // where UpdateCaption could look like:
: //
: // void __fastcall TTest::UpdateCaption()
: // {
: // Form1->Caption = "Updated in a thread";
: // }
: //---------------------------------------------------------------------------
: extern HANDLE Semaphore;
: __fastcall TTest::TTest(bool CreateSuspended)
: : TThread(CreateSuspended)
: {
: FreeOnTerminate = true;
: }
: //---------------------------------------------------------------------------
: void __fastcall TTest::Execute()
: {
: AnsiString strSend, strRcv;
: while (!Terminated)
: {
: Sleep (100);
: strSend = "Thread="+IntToStr(m_iThreadNum)+"\r\n";
:
: WaitForSingleObject(Semaphore, INFINITE);
: strRcv = Form1->m_RS232.SendString(strSend, "\r\n", "");
: if (strRcv.AnsiCompare("\r\n") != 0)
: {
: int i = m_pEditFail->Text.ToInt ();
: m_pEditFail->Text = IntToStr (++i);
: }
: else
: {
: int i = m_pEditSucc->Text.ToInt ();
: m_pEditSucc->Text = IntToStr (++i);
: }
: ReleaseSemaphore (Semaphore, 1, NULL);
: }
: }
: //---------------------------------------------------------------------------
|