퇴근5분전


 WPF 에 프로그래스 바를 사용할때!! 무거워서일까낭..?? 프로그래스에 진행도가 제대로 표현되지 않아서
쓰레드를 보았다.

아래 소스는 두가지를 주안점으로 했다.

첫번째 대리자 비동기 호출은 데브피아에서 비동기 구현관련해서 강좌를 보고 ...
           ( 전에 공부했던 내용이었는데 기억이 안나는건... )

두번째 Thread내에서의 Invoke를 이용해 대리자로써 메서드를 위임하는 부분이 WPF에서는 어찌 되는가를 알아보았다.

# 막상 Invoke를 써보니 Winform과 크게 다른건 없다. Dispatcher라는 프로퍼티에 Invoke를 이용할뿐이다.

 TextBox, Button, ProgressBar   이렇게 구성되어 있다.

   /// <summary>
    /// Window1.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        public delegate void delegateSetTextRender(object i, int cnt);
        public void SetTextRender(object i, int cnt)
        {
            textBox1.AppendText(i.ToString() + "\r\n");
            progressBar1.Value = cnt;
        }

        public void INProgressValue(int Progress)
        {
            progressBar1.Value = Progress;
        }
        public void INProgressMaxValue(int Progress)
        {
            progressBar1.Maximum = Progress;
        }
        public void INProgressMinValue(int Progress)
        {
            progressBar1.Minimum = Progress;
        }


        public delegate void delegateProgress(int i);

        const int SEARCHCOUNT = 20000;

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            // 기본쓰레드로 할때 
            //Thread th = new Thread(new ThreadStart( DoEvent ));
            //th.Start();

            // 비동기로 구현할 때.
               Action ac = new Action(DoEvent);
            AsyncCallback  async = new AsyncCallback(_EndInvoke);
            IAsyncResult ir =  ac.BeginInvoke(async, ac);

        }

        void _EndInvoke( IAsyncResult iar )
        {
           Action ac = iar.AsyncState as Action;
           while (iar.IsCompleted == false)
           {
               Thread.Sleep(100);
           }
           ac.EndInvoke(iar);
       
        }

        /// <summary>
        /// ///////////////////////////////////////////////////
        /// </summary>
        void DoEvent()
        {
            this.Dispatcher.Invoke(new delegateProgress(INProgressValue), new object[] { 0 });
            this.Dispatcher.Invoke(new delegateProgress(INProgressMaxValue),
                                                                                       new object[] { SEARCHCOUNT });
            this.Dispatcher.Invoke(new delegateProgress(INProgressMinValue), new object[] { 0 });


            List<int> sosuList = new List<int>();
            sosuList.Add(2);

            // 검사대상수 1과 2는 건너뜀...
            int number = 3;
        

            // 소수 3만개 찾기위한 루프
            while (sosuList.Count <= SEARCHCOUNT)
            {
                // 소수 검사 결과 일단은 소수라고 의심
                bool result = true;

                // 소수 검사
                double stopNumber = Math.Sqrt(number);
                foreach (int i in sosuList)
                {
                    if ((number % i) == 0)
                    {
                        result = false;
                        break;
                    }
                    if (i > stopNumber) break;
                }
              
                // 진짜 소수면 리스트에 저장
                if (result)
                {
                    this.Dispatcher.Invoke(new delegateProgress(INProgressValue),
                                                                                   new object[] { sosuList.Count });
                    sosuList.Add(number);
                }

                // 검사대상 수 증가
                number++;

                // 검사수에 제한을 둠
                if (number > 20000000) break;
            }

           // this.Dispatcher.Invoke(new delegateProgress(INProgressValue),new object[] { 0 });
            // 추가적으로 파라미터 Thread !!를 구현하는 방법이다.
            Thread th = new Thread(new ParameterizedThreadStart(Dispaly));
          th.Start(sosuList);
                    
        }

        void Dispaly(object prms)
        {
            IList<int> sosuList = prms as IList<int>;
            int cnt = sosuList.Count;
            foreach (int val in sosuList)
            {
                 this.Dispatcher.Invoke(new delegateSetTextRender(SetTextRender),
                                                                                           new object[] { val, --cnt });
               // this.textBox1.AppendText(val.ToString() + "\r\n");
            }
        }
    }

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

FlexGrid : WPF 콤보 컬럼 (Combo Column Type)  (0) 2010.09.07
IValueConverter 사용 데모  (0) 2010.09.06
[WPF] Tab 순환코드  (0) 2010.07.27
툴을 제작 해서 프로젝트를... 진행하다!  (0) 2010.02.26
WPF 3D  (0) 2009.12.29


다음 닷넷 카페에서 소수구하기 2~ 30000 내의 소수 구하기 타임어택을 해본다고 하기에... 나도 한번 해봤다

if와 continue가 소비시간을 그렇게 먹을줄 몰랐넹...

추가하면 할수록 느려지다뉭...

            long dt = DateTime.Now.Ticks;
            bool print = true;         
            for (short i = 2; i < 30000 ; i++){               
                for (short j = 2; j < i ; j++){
                    if (i % j == 0){
                        print = false;break;
                    }
                }
                if (print == true){
                    Console.WriteLine( i.ToString());
                }
                print = true;
            }
            TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - dt);
            MessageBox.Show( ts.ToString() );

VS2005 , CPU : 쿼드 Q8300 , 램 : 4G, OS : XP

이게 가장 빠른 시간이   0.4218750 초이답...    0.4375000...
할때마다 다른데...
릴리즈로 하면 0.1초 빨라짐.

추가 : ...
워... 2~3만이 아니라 2부터 소수 3만개였다.
 3만개 띠웠더니 8초 좀 안되넹..

다른 방법을 찾아봤더니 제곱근 이용하는 방법이 있었다.


        //제곱근을 이용하여 체크. http://hisjournal.net/blog/128
        bool CheckByRoot(int num){
            int rootNum = (int)Math.Sqrt((double)num);
            int div = 0;
            bool value = false; 
            for(div = rootNum; num % div != 0; div--);  
            if(div == 1) value = true;
            else value = false;  
            return value;
            /*http://www.hackerschool.org/HS_Boards/zboard.php?id=Free_Board&no=8479
                "모든 정수는 대칭하는 두수의 곱으로 나타낼수 있다"의 특성을 이용해
                연산시간을 획기적으로 줄였습니다 -_-;;
                예를들어 18이란 정수는 1*18 2*9 3*6 6*3 9*2 18*1 로 나타낼수 있죠.
                여기서는 두 정수의 곱으로만 나타냈지만 실제로는 실수로도 가능합니다.
                3루트3 * 2루트3 로도 나타낼수 있죠.
                이처럼 대칭되어지는 두수의 곱으로 나타낼수 있기때문에 실제로 소수인지 확인
                하기위해서는 대칭되어지는 점[입력값의 루트값 즉 sqrt()함수를 이용한 결과값]
                까지만 연산을 해주면 된다는 결론이 나옵니다.
                그래서 두번째 방법에 하나의 변수를 더 추가하여[sqrt_number] sqrt값을 만들어
                내고 for문의 범위를 이 변수의 값까지로 한정시켰습니다.
                속도는....가히 눈부시군요 -_- 2번째 버젼에서 39초나 걸렸던 "1234567891" 란
                정수의 소수확인시 1초도 안걸립니다.....
                결론: 알고리즘이란게 재밌군요. 이제 다른 주제로 알고리즘 연구를 해봐야겠습니
                      다.
                */
        }

이거 적용해도 ... 그닥.. 0.0625초는 안나온다.

소인수분해를 이용해서 소스를 작성했으나...  실패했다.
이유인즉 소수를 찾기위해 수를 소수로 인수분해하려면 소수값을 가지고 있어야 하는데 꾀나 많은 소수들이 있어야 한다는... 벽에 부딪혔다. 30개를 가지고 131까지도 계산 못한다..

 int CheckBy(int num)
        {
            /*소인수분해 .
             
소인수분해를 할때는 가장 작은 소수부터 나누는게 좋습니다.
60을 소인수분해 한다고 하면,
60는 2의 배수죠? 그러면 2*30이 됨니다
그런데 30도 2의 배수죠? 그러면 2*2*15가 되죠..
15는 3의 배수입니다. 그러면 2*2*3*5
5는 소수이므로 더 이상 할 필요가 없습니다.
따라서 60을 소인수분해 하면 2²*3*5가 되는 것입니다
*/
            int[] primeNum = new int[] {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127};
            List<int> ar = new List<int>();
            int primeIndex = 0;
            int TempValue = 0;
            int modTempValue = 0;
            int primeCount = 0;
            TempValue = num;
            do
            {
               if( TempValue == 1 )
               {
                   ar.Add(TempValue);
                   break;
               }
               if (TempValue % primeNum[primeIndex] == 0)
               {
                   ar.Add(TempValue);
                   TempValue = TempValue / primeNum[primeIndex];
               }
               else
               {
                   primeIndex++;
               }
               
            } while (true); // 3개부터는 ~
            return ar.Count;
        }

줸장 ㅡ,.ㅡ;;


0.0625초는 대체 어떻게 나온거쥐?


실패했따 ㅡ.,ㅡ;;; 슬프다.. 



추가

카페에 갔더니 소스가 올라왔다... 봤더니 ~~ 와!! 대박!...
출력까지 포함시켜도 2초 정도 나온다.

제곱근과 소인수분해를 복합적으로 적용시켜놓은 소스였다... 

감탄뿐이 안나옴... 알고리즘 공부 좀 다시 해야겠다.





'# 2) .Net ( Vs 2005 ) > 기타' 카테고리의 다른 글

이미지 미리보기~  (0) 2010.08.31
글꼴 폰트 관련 MSDN 링크  (0) 2010.08.10
[GDI+] Matrix 객체 사용해보기...  (0) 2010.07.27
IFormattable  (0) 2010.07.15
트리노드 검색해서 확장하기...  (0) 2010.03.17


훈스에 올라온 질문중에 한글이 들어간 파라미터를 사용하는 OpenAPI 주소를 넣으면
xml을 제대로 쿼리해오지 못한다고 해서...
 
URI에 한글이 있고 없고 차이였는데... WebClient에 넣으면 자동 인코딩이되어 데이타가 안나오고
WebBrowser에 넣으면 제대로 데이타가 나온다.


WebClient로 해봤으나.. 역시 기초부족일테고, httpWebRequest도 해보고 WebRequest....

다 써봤는데 젠장... 제대로 안온다.?

Explorer에 주소 치고 엔터 치면 가져온다...

그래서 WebBrowser에 Url 속성에 넣고 가져와봤더니 가져온다..???

여기서..........         겁나 깝깝했다... 하나는 가져오고 하나는 가져오지 않는다.

근데 WebBrowser는 컨트롤인데 좀 패키지화 시키기 어정쩡한?

그래서 나온 소스가?

 delegate void GetXml(string _xml);
        private void MM(Uri ur, GetXml write)
        {
            WebBrowser wb = new WebBrowser();
            {
                wb.Url = ur;
                wb.DocumentCompleted += (s, e) =>
                {
                    write(wb.DocumentText);
                    using (wb) { /* 객체를 없애기 위해 */ };
                };
                wb.Refresh(WebBrowserRefreshOption.Completely);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Uri ur = new Uri("~~~~~~~");
            MM(ur, x => [webBrowser1.DocumentText] = x);
        }


풋... 좀 깬다 ㅡ.,ㅡ;;;

이건.. 유틸용으로다... 쩝.....
  public class Util
        {
            public delegate void GetXml(string _xml);
            public static void MM(Uri ur, GetXml write)
            {
                WebBrowser wb = new WebBrowser();
                {
                    wb.Url = ur;
                    wb.DocumentCompleted += (s, e) =>
                    {
                        write(wb.DocumentText);
                        using (wb) { /* 객체를 없애기 위해 */ };
                    };
                    wb.Refresh(WebBrowserRefreshOption.Completely);
                }
            }
        }

        // 사용할때~
        private void button1_Click(object sender, EventArgs e)
        {
            Uri ur = new Uri("~~~~~~~~");
            Util.MM(ur, x => [webBrowser1.DocumentText]  = x);
        }


더워서 더는 못하겠따~!!!

'# 3) .Net ( Vs 2008 ) > C#' 카테고리의 다른 글

포스트 잇 처럼 메모하는 레이아웃!!  (0) 2010.09.30
Ms Access 사용하기 예제소스.  (0) 2010.08.11
LINQ 그룹바이... 훌...  (0) 2010.07.30
Double.Parser()...  (0) 2010.07.19
암묵적인 형변환? 코드...?  (0) 2010.05.18