'Common Tip/장애 경험치'에 해당되는 글 3건

  1. 2009.03.13 밑에꺼 이어서
  2. 2009.03.12 Form.Show와 스레드 관련해서 여쭙니다... | Thread Program
  3. 2008.06.05 DBConnection 지식인 질문사항 #1
Common Tip/장애 경험치2009. 3. 13. 08:49

우선, 생성자를 보면은 myWorker 필드를 설정하는 내용이 나옵니다.

            myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
            myWorker.WorkerReportsProgress = true;
            myWorker.ProgressChanged +=

new ProgressChangedEventHandler(myWorker_ProgressChanged);
            myWorker.RunWorkerCompleted +=

new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
 

DoWork 이벤트, ProgressChanged 이벤트, RunWorkerCompleted 이벤트에 적절한

이벤트 핸들러를 설정했습니다.

 그런데, myWorker.WorkerReportsProgress = true; 라는 문장이 있죠.

이렇게 WorkerReportsProgress 프로퍼티를 true 값으로 설정해야,

ProgressChanged 이벤트가 일어나게 됩니다.

DoWork 이벤트 핸들러를 살펴볼까요?

        void myWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 5; ++i)
            {
                Thread.Sleep(1000);
                myWorker.ReportProgress(i);
            }

            Thread.Sleep(1000);
        }

보시다시피, for 문 안에서 1초 간격으로  ReportProgress() 메소드를 호출하는데,

이 메소드를 호출하면 ProgressChanged 이벤트가 일어나므로,

백그라운드 작업 도중에 사용자 인터페이스를 변경하는 작업을 수행할 수 있게 됩니다.

        void myWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.label1.Text = "No. " + e.ProgressPercentage.ToString();
        }

DoWork 이벤트 핸들러에서 ReportProgress() 메소드 호출할 때마다 일어나는

ProgressChanged 이벤트 핸들러는 단순히 레이블의 텍스트를 변경합니다.

원한다면, 다른 효과를 적용할 수도 있습니다. 예를 들면, 레이블의 배경 색상을 변경할 수도 있죠.

이제, DoWork 이벤트 핸들러 작업이 끝나면,

RunWorkerCompleted 이벤트가 일어나므로, 이 이벤트에 대한 이벤트 핸들러가 실행됩니다.

        void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.label1.Text = "Completed!";
        }

최종적으로, 레이블의 텍스트를 변경하는 것 밖에 없습니다.

아래에는 버튼을 클릭 이벤트 핸들러가 나와 있는데,

IsBusy 프로퍼티를 검사하는 코드가 나와 있습니다.

        private void button1_Click(object sender, EventArgs e)
        {
            if (myWorker.IsBusy != true)
myWorker.RunWorkerAsync();
        }

이렇게 해야 하는 이유는,

버튼의 클릭 이벤트 핸들러는 최소 6초가 소요되는 작업을 수행하는데,

두 번 이상 버튼을 클릭할 수도 있게 됩니다.

만일, 두 번 이상 버튼을 클릭하면 이미 백그라운드에서 작업이 진행되고 있는데,

또다른 작업을 요청하게 되므로 에러가 발생합니다.

따라서,  IsBusy 프로퍼티를 검사하여, 백그라운드 작업이 실행 중인지 검사하여,

작업이 실행된다면, 아무일도 하지 않도록 했습니다.

잘 참고하시면, 굳이 타이머를 이용하지 않고도,

훨씬 안정적인 다중 쓰레드 프로그램을  만들 수 있을 겁니다.

잘 이해 안되는 게 있으면 쪽지 주세요.

그럼. 수고하세요~

http://msdn.microsoft.com/ko-kr/library/48cfdff6(VS.80).aspx
 

Posted by penguindori
Common Tip/장애 경험치2009. 3. 12. 15:20

http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=17&MAEULNo=8&no=106756&ref=106756
http://blog.naver.com/hanbyi?Redirect=Log&logNo=110012603567 <-- 이거 공부하자

타이머 말고,
BackgroundWorker 라는 클래스를 사용하여 문제를 해결할 수 있습니다.
BackgroundWorker 클래스는 말그래도 메인 UI 쓰레드가 아닌 다른 쓰레드에서 작업을 처리할 수 있도록
도와주는 .NET 클래스입니다.
이 클래스를 사용하면 복잡한 쓰레드 문제를 피할 수 있으며 원하는 결과를 쉽게 얻을 수 있습니다.
방법은 다음과 같습니다.

메인 UI 쓰레드가 아닌 다른 쓰레드에서 폼의 레이블 컨트롤을 매 초마다 업데이트 하도록 하는 겁니다.
BackgroundWorker 클래스에 대해 잠시 설명하자면..
 BackgroundWorker 클래스의 인스턴스를 생성한 다음,
이 인스턴스의 RunWorkerAsync() 메소드를 실행하면,
백그라운드 작업이 진행됩니다. 이 때, DoWork 이벤트가 일어나게 됩니다.

 즉, DoWork 이벤트에 적절한 이벤트를 핸들러를 추가하면, 이 이벤트 핸들러가
RunWorkerAsync() 메소드 실행시에 다른 쓰레드에서 실행된다는 뜻입니다.

 실질적인 백그라운드 작업 코드를 DoWork 이벤트 핸들러에 추가하면 되겠습니다.
DoWork 이벤트 핸들러가 백그라운드 작업을 진행하는 동안에,중간 중간 정보를 반환받아야 한다면,
(이번 문제처럼 중간 중간 레이블 컨트롤을 업데이트 한다는 것처럼)

 DoWork 이벤트 핸들러 안에서, ReportProgress() 메소드를 호출해야 합니다.
이 메소드가 호출되면,  ProgressChanged 이벤트가 일어나는데, 
이 이벤트에 대한 이벤트 핸들러에 레이블 컨트롤을 업데이트 하는 논리를 추가하면 되겠습니다.
마지막으로 DoWork 이벤트 핸들러의 모든 작업이 끝나면, RunWorkerCompleted 이벤트가 일어납니다.

이 이벤트에 대한 이벤트 핸들러에서 최종 마무리 작업을 수행하면 되겠습니다.
이러한 절차를 잘 염두에 두면, 매우 쉬운 백그라운드 작업 코드를 작성할 수 있답니다.

 다음과 같은 코드를 살펴 보죠.

 public partial class Form1 : Form
{
        private BackgroundWorker myWorker = new BackgroundWorker(); 

        public Form1()
        {
            InitializeComponent(); 

            myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
            myWorker.WorkerReportsProgress = true;
            myWorker.ProgressChanged += new ProgressChangedEventHandler(myWorker_ProgressChanged);
            myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
        }

        void myWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 5; ++i)
            {
                Thread.Sleep(1000);
                myWorker.ReportProgress(i);
            }

            Thread.Sleep(1000);
        }

        void myWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.label1.Text = "No. " + e.ProgressPercentage.ToString();
        }

        void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.label1.Text = "Completed!";
        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (myWorker.IsBusy != true)
            myWorker.RunWorkerAsync();
        }
 }

Posted by penguindori

안녕하세요. DB 연동이 잘 안되서 이렇게 지식인에 물어봅니다.

11g 입니다. 참고로 ^^;


tnsnames.ora


DBDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracletest.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = DBDB)
      (SERVER = DEDICATED)
     
    )
  )


ORCL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracletest.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orcl)
    )
  )

--------------------

listener.ora


LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = oracletest.com)(PORT = 1521))
    )
  )


프로그램 실행시 이런 에러가 발생 합니다.

사용자 삽입 이미지

프로그램 소스 입니다.


private string connectionString = "Data Source=oracletest.com;Integrated Security=yes;pwd=1212;uid=okok";


  private void Form1_Load(object sender, EventArgs e)
        {
         
            using (OracleConnection connection = new OracleConnection(connectionString))
            {
                try
                {
                    OracleCommand cmd = new OracleCommand();
                    cmd.Connection = connection;
                    connection.Open();
                    MessageBox.Show("이상없음");
                }
                catch (Exception k)
                {
                    MessageBox.Show(k.Message.ToString());
                }
            }
        }


위의 내용중 잘못된 부분을좀 알려주시거나 혹 의심이 가는 부분이 있다면 많은 답변 부탁드리겠습니다.

(__)(^^)


수집허용 | 아이디비공개

의견 쓰기

sewooim님의 지식을 나누어주세요!
답변하시면 내공 10점을, 답변이 채택되면 내공 125점(채택25+추가100)을 드립니다.
>나도 답변하기

질문자 선택

re: C# Oracle DB 연동이 잘 안되요. 도와주세요. 내공 100 겁니다.

ngmaster

답변채택률 76.5%

2008.06.03 12:51

질문자인사 감사합니다. 소중한 답변 정말 감사합니다. 하시는일 항상 복받으시길 바랍니다.

Data Source=oracletest.com; 이 부분에서 잘못되었네요.

데이터 소스에 접근하기 위한 알리어스가 필요합니다.

Data Source=oracletest.com/DBDB; 와 같이 적어주셔야 해요.

또는 Data Source=DBDB; 와 같이 적어주셔도 됩니다.

물론 framework 버전과 oracle 버전에 따라서 약간 틀릴수도 있어요..;;


저는 11g는 아직 사용해보진 않았지만 크게 틀리진 않을거 같네요-_-;;

tnsnames에 정의해준 알리어스 (DBDB 또는 ORCL)를 뒤에 적어주고 해보세요.

의견 2

  • sewooim
    안녕하세요. 답변 감사드립니다. 해당 말씀하신 부분이 틀린점 맞고 또한 Integrated Security=yes 이부분을 제거해 주니깐 잘 되네요 ^^;; 혹 저 보안 관련 부분에 대한 내용을 아시면 답변 (Integrated Security=yes) 부탁드립니다. 문제는 해결이 되었어요 일단은 ^^ 내일쯤 보고 내공을 드리도록 하겠습니다. 08.06.03 23:44
  • ngmaster
    Integrated Security 요 부분은 저도 정확하게는 파악하고 있진 않습니다. 만약 그 부분에 true또는 ssip던가..;; 아무튼 지정하게 되면 아참..yes도..마찬가지구요... 윈도우즈 통합계정을 사용한다는 뜻으로 님의 윈도우즈 계정으로 디비에 접속을 하게 될겁니다. 그래서 userid와 pwd를 입력할 필요가 없으며, false 또는 no로 설정하시면 디비에 접속할 계정 및 비밀번호를 입력해야 합니다. 기본적으로 false로 사용하는걸로 알구 있구요. 그 부분은 속성이기 때문에(기본값 false) 삭제하셔도 상관이 없습니다. 08.06.04 10:21
Posted by penguindori