'분류 전체보기'에 해당되는 글 159건

  1. 2009.03.13 기본 Threading Study #1
  2. 2009.03.13 밑에꺼 이어서
  3. 2009.03.12 Form.Show와 스레드 관련해서 여쭙니다... | Thread Program
  4. 2009.03.06 dd
  5. 2009.03.03 C++ template 와 C# Generic 차이점
  6. 2009.03.03 형식 매겨 변수 #3
  7. 2009.03.03 형식 매개변수 #2
  8. 2009.03.03 형식 매개 변수에 대한 제약 조건
  9. 2009.03.02 test
  10. 2009.02.24 ㅠㅠ
Common C#/C# Threading2009. 3. 13. 16:28

[form1 sorces]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ButtonExam
{
    public partial class Form1 : Form
    {
        ButtonExam.Pro form = new Pro();
        public ProgressBar okpro = null;
       
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("This is Main Thread");
           
            form.Show();
            form.Text = "안녕";
        }

        private void ThreadTask()
        {
            int stp;
            int newval;
            Random rnd = new Random();
            okpro = form.getProg();
            while (true)
            {
                stp = okpro.Step * rnd.Next(-1, 2);
                newval = okpro.Value + stp;

                if (newval > okpro.Maximum)
                    newval = okpro.Maximum;
                else if (newval < okpro.Minimum)
                    newval = okpro.Minimum;

                okpro.Value = newval;

                Thread.Sleep(100);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Thread trd = new Thread(new ThreadStart(this.ThreadTask));
         trd.IsBackground = true;
         trd.Start();
        }
    }
}




[form2 sorces]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ButtonExam
{
    public partial class Pro : Form
    {

        public ProgressBar getProg()
        {
            return this.progressBar1;
        }

        public Pro()
        {
            InitializeComponent();
        }

    }
}



 

Posted by penguindori
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
카테고리 없음2009. 3. 6. 13:16

dd

Posted by penguindori

http://msdn2.microsoft.com/ko-kr/library/c6cyy67b(VS.80).aspx 참조

 - C++에서는 템플릿의 모든 형식 매개 변수에 대해서는 유효하지 않을 수 있는 코드가 허용되며 이러한 코드는 형식 매개 변수로 사용되는 특정 형식에 대해 검사를 받습니다. C#에서는 제약 조건을 충족하는 모든 형식과 함께 사용할 수 있도록 클래스의 코드를 작성해야 합니다. 예를 들어, C++의 경우 형식 매개 변수의 개체에 대해 + 및 - 산술 연산자를 사용하는 함수를 작성할 수 있습니다. 이 경우 이러한 연산자를 지원하지 않는 형식으로 템플릿을 인스턴스화할 때 오류가 발생합니다. C#에서는 이러한 함수를 작성할 수 없고 제약 조건에서 추론 가능한 언어 구문만 사용할 수 있습니다.

코드로 보면

[C++]
template<class T>
class WidgetT
{
    void DoSomething(T t)
    {
        t.Process();
    }

};

위와 같은 구현이 가능했지만

[C#]
class WidgetT<T>
{
    public void DoSomething(T t)
    {
        t.Process();
    }
};

이렇게 구현하면 컴파일 에러가 납니다.
class T가 Process()를 구현하는지 알수없기 때문에 허용해 줄 수 없다는 이야기 입니다.
하지만 T가 Process()를 구현하는 것을 확인해주면 허용해 줄 수 있다는 말도 되겠지요.

[C#]
class WidgetT<T> where T : ISomeInterface
{
    public void DoSomething(T t)
    {
        t.Process();
    }
};

interface ISomeInterface
{
    void Process();
};

이렇게 정의하고 실제 구현부분에서는

class SomeHandler : ISomeInterface
{
    public void Process()
    {
        // 구현
    }
};


SomeHandler handler = new SomeHandler();
WidGet<SomeHandler> wg = new WidGet<SomeHandler>();
wg.DoSomething(handler);

이렇게 사용하시면 됩니다.

제네릭의 형식매개변수에 대한  좀더 자세한 설명은 http://msdn2.microsoft.com/ko-kr/library/d5x73970(VS.80).aspx 에 있습니다.

[출처] C++ 템플릿과 C# 제네릭의 차이점 #2|작성자 자바워크

Posted by penguindori

형식 매개 변수를 제한하면, 허용되는 작업의 수 및 제한하는 형식과 해당 상속 계층 구조의 모든 형식에서 지원하는 메서드에 대해 허용되는 호출의 수를 늘릴 수 있습니다. 따라서 제네릭 클래스나 메서드를 디자인할 때 System.Object에서 지원하지 않는 메서드를 호출하거나 제네릭 멤버에 대해 단순한 할당 이상의 작업을 수행하려는 경우에는 형식 매개 변수에 제약 조건을 적용해야 합니다.

where T : class 제약 조건을 적용할 때는 형식 매개 변수에 대해 == 및 != 연산자를 사용하지 않는 것이 좋습니다. 이러한 연산자에서는 값이 같은지 확인하는 대신 참조가 동일한지만 테스트하기 때문입니다. 인수로 사용되는 형식에서 이러한 연산자를 오버로드한 경우에도 마찬가지입니다. 다음 코드에서는 이러한 경우의 예를 보여 줍니다. String 클래스에서 == 연산자를 오버로드해도 false가 출력됩니다.

C# 코드 복사
public static void OpTest<T>(T s, T t) where T : class
{
    System.Console.WriteLine(s == t);
}
static void Main()
{
    string s1 = "foo";
    System.Text.StringBuilder sb = new System.Text.StringBuilder("foo");
    string s2 = sb.ToString();
    OpTest<string>(s1, s2);
}

이러한 방식으로 동작하는 이유는 컴파일 시 컴파일러에는 T가 참조 형식이라는 정보만 제공되므로 모든 참조 형식에 유효한 기본 연산자가 사용되기 때문입니다. 값이 동일한지 테스트하려면 where T : IComparable<T>제약 조건을 함께 적용하고 제네릭 클래스를 생성하는 데 사용되는 모든 클래스에서 해당 인터페이스를 구현하는 것이 좋습니다.

 바인딩되지 않은 형식 매개 변수
공용 클래스 SampleClass<T>{}의 T와 같이 제약 조건이 없는 형식 매개 변수를 바인딩되지 않은 형식 매개 변수라고 합니다. 바인딩되지 않은 형식 매개 변수에는 다음과 같은 규칙이 적용됩니다.

!= 및 == 연산자를 사용할 수 없습니다. 구체적인 형식 인수에서 이러한 연산자를 지원하리라는 보장이 없기 때문입니다.

바인딩되지 않은 형식 매개 변수와 System.Object 사이에 변환하거나 이 매개 변수를 임의의 인터페이스 형식으로 명시적으로 변환할 수 있습니다.

바인딩되지 않은 형식 매개 변수를 null과 비교할 수 있습니다. 바인딩되지 않은 매개 변수를 null과 비교하는 경우 형식 인수가 값 형식이면 비교 결과로 항상 false가 반환됩니다.

 naked 형식 제약 조건
제네릭 형식 매개 변수를 제약 조건으로 사용하는 경우 이를 naked 형식 제약 조건이라고 합니다. naked 형식 제약 조건은 다음 예제에서와 같이 자체 형식 매개 변수가 있는 멤버 함수에서 해당 매개 변수를 포함 형식의 형식 매개 변수로 제한해야 하는 경우에 유용합니다.

C# 코드 복사
class List<T>
{
    void Add<U>(List<U> items) where U : T {/*...*/}
}

위 예제에서 T는 Add 메서드의 컨텍스트에서는 naked 형식 제약 조건이고 List 클래스의 컨텍스트에서는 바인딩되지 않은 형식 매개 변수입니다.

naked 형식 제약 조건은 제네릭 클래스 정의에도 사용할 수 있습니다. naked 형식 제약 조건도 다른 모든 형식 매개 변수와 마찬가지로 꺾쇠괄호 안에 선언해야 합니다.

C# 코드 복사
//naked type constraint
public class SampleClass<T, U, V> where T : V { }

컴파일러에서는 naked 형식 제약 조건이 System.Object에서 파생된다는 점을 제외하고는 이 제약 조건에 대해 어떠한 정보도 알 수 없으므로 naked 형식 제약 조건과 제네릭 클래스를 함께 사용할 필요는 거의 없습니다. 제네릭 클래스에 대해 naked 형식 제약 조건을 사용하는 경우로는 두 형식 매개 변수 사이에 반드시 상속 관계가 있도록 정의하는 경우를 들 수 있습니다.


Posted by penguindori

C# 코드 복사
public class Employee
{
    private string name;
    private int id;

    public Employee(string s, int i)
    {
        name = s;
        id = i;
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int ID
    {
        get { return id; }
        set { id = value; }
    }
}

public class GenericList<T> where T : Employee
{
    private class Node
    {
        private Node next;
        private T data;

        public Node(T t)
        {
            next = null;
            data = t;
        }

        public Node Next
        {
            get { return next; }
            set { next = value; }
        }

        public T Data
        {
            get { return data; }
            set { data = value; }
        }
    }

    private Node head;

    public GenericList() //constructor
    {
        head = null;
    }

    public void AddHead(T t)
    {
        Node n = new Node(t);
        n.Next = head;
        head = n;
    }

    public IEnumerator<T> GetEnumerator()
    {
        Node current = head;

        while (current != null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }

    public T FindFirstOccurrence(string s)
    {
        Node current = head;
        T t = null;

        while (current != null)
        {
            //The constraint enables access to the Name property.
            if (current.Data.Name == s)
            {
                t = current.Data;
                break;
            }
            else
            {
                current = current.Next;
            }
        }
        return t;
    }
}

제약 조건을 사용하면 형식 T의 모든 항목이 Employee 개체이거나 Employee에서 상속된 개체임을 보장할 수 있으므로 제네릭 클래스에서 Employee.Name 속성을 사용할 수 있습니다.

여러 제약 조건을 동일한 형식 매개 변수에 적용할 수 있고 제약 조건 자체가 제네릭 형식일 수도 있습니다. 예를 들면 다음과 같습니다.

C# 코드 복사
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
    // ...
}

 

Posted by penguindori
2009. 3. 3. 17:05

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

카테고리 없음2009. 3. 2. 17:37

안녕하세요. 박세우 입니다.

Class로 만들어서 가져오는 습관이 되다 보니 통으로 미처 기술해 주지 못한 부분을 파란색으로 표시하였습니다.

;; ㅠㅠ 제송합니다. 윈폼 요청하신 부분을 개발 중에 정신이 없어서 ;; 사소한 부분을 발견하지 못했네요;

  

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Data.OracleClient;

 

namespace Login

{

    public partial class Form2 : Form

    {

        OracleConnection oConn;

        OracleCommand oComm;

        OracleParameter[] oPar;

 

        public Form2()

        {

            InitializeComponent();

        }

 

        private void Form2_Load(object sender, EventArgs e)

        {

            oConn = new OracleConnection("Data Source=mi;User ID=midas;Password=midas123");

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            StringBuilder sbSql = new StringBuilder();

            oConn.Open();

 

            try

            {

                sbSql.Append(" select userid,userpwd,username  ");

                sbSql.Append("  from midas_user ");

                sbSql.Append("  WHERE userid  = :userid ");

                sbSql.Append("  AND userpwd  = :userpwd ");

 

                oPar = new OracleParameter[2];

                oPar[0] = new OracleParameter(":userid", textBox1.Text);

                oPar[1] = new OracleParameter(":userpwd", textBox2.Text);

 

                oComm = new OracleCommand(sbSql.ToString(), oConn);

 

                oComm.Parameters.Add(oPar[0]);

               oComm.Parameters.Add(oPar[1]);

 

                OracleDataReader dr = oComm.ExecuteReader(CommandBehavior.CloseConnection);

                oComm.Parameters.Clear();

 

                dr.Read();

 

                MessageBox.Show(dr["USERNAME"].ToString());

                MessageBox.Show(dr["userid"].ToString());

               

 

            }

            catch (Exception ex) { string ok = ex.Message.ToString(); }

 

 

        }

    }

}

 


Posted by penguindori

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Xml;
using System.IO;

namespace Hynix.Core
{
    /// <summary>
    /// Sql Command 실행을 도와주는 클래스
    /// </summary>
    public class SqlHelper
    {
        public static void ExcuteCommand(string strConn, string strCmd)
        {
            ExcuteCommand(strConn, strCmd, false, null);
        }

        public static void ExcuteCommand(SqlTransaction tran, string strCmd)
        {
            ExcuteCommand(tran, strCmd, false, null);
        }

        public static void ExcuteCommand(SqlTransaction tran, string strCmd, bool IsSP, SqlParameter[] oParams)
        {
            SqlCommand oCmd = new SqlCommand(strCmd, tran.Connection, tran);
            oCmd.CommandTimeout = int.Parse(Config.Instance.GetValue("TIMEOUT"));

            if (IsSP == true) { oCmd.CommandType = CommandType.StoredProcedure; }

            if (oParams != null)
            {
                for (int i = 0; i < oParams.Length; i++)
                {
                    oCmd.Parameters.Add(oParams[i]);
                }
            }

            oCmd.ExecuteNonQuery();
        }

        public static void ExcuteCommand(string strConn, string strCmd, bool IsSP, SqlParameter[] oParams)
        {
            if (strConn.IndexOf("Connect Timeout") < 0)
            {
                strConn += ";Connect Timeout=" + Config.Instance.GetValue("TIMEOUT") + ";";
            }

            SqlConnection oConn = new SqlConnection(strConn);
            SqlCommand oCmd = new SqlCommand(strCmd, oConn);
            oCmd.CommandTimeout = int.Parse(Config.Instance.GetValue("TIMEOUT"));

            if (IsSP==true)
            {
                oCmd.CommandType = CommandType.StoredProcedure;

                if (oParams != null)
                {
                    for (int i = 0; i < oParams.Length; i++)
                    {
                        oCmd.Parameters.Add(oParams[i]);
                    }
                }
            }

            oConn.Open();
            oCmd.ExecuteNonQuery();
            oConn.Close();
        }

        public static DataSet ExcuteDataSet(string strConn, string strCmd)
        {
            return ExcuteDataSet(strConn, strCmd, false, null);
        }

        public static DataSet ExcuteDataSet(string strConn, string strCmd, bool IsSP, SqlParameter[] oParams)
        {
            if (strConn.IndexOf("Connect Timeout") < 0)
            {
                strConn += ";Connect Timeout=" + Config.Instance.GetValue("TIMEOUT") + ";";
            }

            SqlConnection oConn = new SqlConnection(strConn);
            SqlCommand oCmd = new SqlCommand(strCmd, oConn);
            oCmd.CommandTimeout = int.Parse(Config.Instance.GetValue("TIMEOUT"));

            if (IsSP==true)
            {
                oCmd.CommandType = CommandType.StoredProcedure;

                if (oParams != null)
                {
                    for (int i = 0; i < oParams.Length; i++)
                    {
                        oCmd.Parameters.Add(oParams[i]);
                    }
                }
            }

            SqlDataAdapter da = new SqlDataAdapter(oCmd);

            DataSet ds = new DataSet();
            da.Fill(ds);
            return ds;
        }
    }
}

Posted by penguindori