|
메인 소스에서
: : : m_pThread[0]->m_pEditFail = Edit2;
: : : m_pThread[0]->m_pEditSucc = Edit7;
...
스레드에서
: : : 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);
: : : }
하였으므로
서브스레드에서 메인스레드의 VCL에 접근하고 있습니다. (m_pEditFail, m_pEditSucc)
따라서 Synchronize를 사용하시면 될것입니다.
Synchronize 소스를 함 보시면 아시겠지만 내부적으로 새로운 기술은 아니고 Event + CriticalSection을 사용하고있습니다.(win32의 경우)
VCL이외의 데이터라도 동기화의 목적으로 사용하셔도 됩니다.
worldfip 님이 쓰신 글 :
: 메인폼에 있는 VCL은 공용으로 사용하는것은 없습니다.
: Synchronize 는 VCL컨트롤에만 적용되는 것으로 알고 있습니다.
: // Important: Methods and properties of objects in VCL can only be
: // used in a method called using Synchronize
:
:
:
: 권상득 님이 쓰신 글 :
: : 메인폼에 있는 놈들을 하위 스레드에서 사용하려면.. 반드시 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);
: : : }
: : : }
: : : //---------------------------------------------------------------------------
|