GSI

개인적으로 요즘 맥 UI가 맘에 든다.
아이팟은 하나 가지고 싶었는데 핸드폰과 똑같은 디자인의 아이팟..
괜찮은거 같다...

[관련기사] : http://news.naver.com/hotissue/read.php?hotissue_id=236&hotissue_item_id=21285&office_id=030&article_id=0000190763&section_id=8&is_photo=true&page=1

Posted by gsi
:

PC방 등록제...

내 일상 2007. 9. 16. 23:46 |

11월 부터 PC방 등록제를 한다는 기사가 나왔다.
대충 6000여곳이 퇴출 위기라고 하는뎅..

저번에 어딘가에는 pc방이긴 한데 가정집을 변형해서 하던데..
그때 카트 라이더를 pc방 혜택 없이 정신없이 한때가 기억 나네요 ^^..

음.. pc방에서 살고 있는 게이머들은 다들 어디로 갈지..
많은 변화가 있을까..

Posted by gsi
:

ADO .NET 모델 - 기초내용

DB&XML 2007. 9. 16. 23:03 |

ADO .NET 객체 모델

ADO.NET 클래스는 크게 두 개의 컴포넌트로 나누어져 있다. 즉, 물리적인 데이터 저장소와의 커뮤니케이션을 다루는 데이터 공급자(Data Providers : 때에 따라 Managed Provider 라고도 부른다)와 실제 데이터를 나타내 주는 DataSet으로 나누어진다. 이들 두 가지 컴포넌트들은 모두 WebForm이나 WinForm과 같은 데이터 사용자(Data Consumers)와 통신을 할 수 있다.

데이터 공급자(Data Providers)
데이터 공급자 컴포넌트는 데이터 소스에 대하여 특별한 역활을 한다. .NET 프레임워크는 두개의 데이터 공급자를 포함한다. 하나는 OLE DB 데이터 소스와 통신을 하는 일반 데이터 공급자이고, 또 하나는 Microsoft SQL Server 7.0 버젼 및 그 이후 버전에 최적화 시킨 SQL Server 데이터 공급자이다. 오라클이나 DB2와 같은 기타 데이터베이스를 위한 데이터 공급자도 사용 가능할 것으로 기대된다. 또한, 개발자가 자신만의 것을 만들어 사용할 수도 있다.

.NET 프레임워크에 포함되어 있는 두 개의 데이터 공급자는 서로 동일한 객체를 포함하고 있다. 비록, 포함하고 있는 각각의 객체가 서로 다른 이름을 가지고 있고 일부 속성과 메서드가 다르지만, 이들은 동일한 객체이다. 이를 설명하기 위해서, SQL Server 공급자 객체는 SQL이라는 이름으로 시작하고(예를 들어, SqlConnection), OLE DB객체는 OleDB라는 이름으로 시작한다.(예를 들어, OleDbConnection).

Connection 객체는 데이터 소스와의 물리적인 연결을 나타낸다. Connection 객체의 속성은 데이터 공급자(OLE DB 데이터 공급자의 경우), 연결하고자 하는 데이터 소스와 데이터베이스, 그리고 연결하는 동안 사용할 문자열을 결정짓는다. Connection 객체의 메서드는 매우 간단하다. 즉, 연결을 열거나 닫고, 데이터베이스를 변경하거나 트랜잭션을 관리한다.

Command 객체는 데이터 소스에 대해 실행될 SQL 문 또는 저장 프로시저(stored procedure)를 나타낸다. Connection 객체와는 상관없이 독립적으로 Command 객체를 생성하고, 실행할 수 있다. 또한, DataSet과 데이터 소스와의 통신을 위해 DataAdapter 객체가 Command 객체를 사용한다. Command 객체는 단일 값, 한 개 또는 그 이상의 행(row) 집합, 또는 전혀 값을 리턴하지 않는 SQL 문과 저장 프로시저를 지원할 수 있다.

DataReader는 데이터 소스의 데이터 스트림을 전방향(forward-only) 및 읽기 전용으로 포함하기 위한 빠르고 오버헤드가 적은 객체이다. DataReader 객체는 코드에서 직접 생성할 수 없고, 오직 Command 객체의 ExecuteReader 메서드를 호출할 때만 생성할 수 있다.

DataAdapter는 데이터 공급자 객체들 중에서 기능적으로 가장 복합한 객체이다. DataAdapter는 Connection과 DataSet 사이의 브릿지를 제공한다. DataAdapter는 네 개의 Command 객체, 즉 SelectCommand, UpdateCommand, InsertCommand, DeleteCommand를 포함한다. DataSet을 채우기 위해서 SelectCommand를 사용하고, 다른 나머지 세 개의 객체는 변경 내용을 다시 데이터 소스에 전달할 때 사용한다.

Microsoft ActiveX Data Objects(ADO)
기능적인 측면에서, Connection과 Command 객체는 해당되는 ADO 및 대응되는 객체와 어느 정도 동일하다(주요한 차이점은 서버측 커서가 제동되지 않는다는 것이다.) 반면에, DataReader 함수는 소방 호수 커서와 같다(전방향 읽기 전용의 특성으로 인하여), ADO에서 DataAdapter와 DataSet은 동일한 것이 없다.


DataSet
DataSet은 데이터를 나타내기 위한 메모리 상주형 데이터이다. DataSet의 구조는 아래 그림과 같으며, 테이블과 테이블 사이의 관계로 구성된 관계형 데이터베이스를 간단히 나타낸 형태와 같다고 볼 수 있다. DataSet이 항상 데이터 소스와 연결되어 있지 않다는 것을 이해하는 것이 중요하다. DataSet이 가지고 있는 데이터를 어디에서 가져왔는지 알지 못하지만, 실제적으로는 여러 데이터 소스의 데이터를 포함할 수 있다.

DataSet은 DataTableCollection과 DataRelationCollection이라는 두 개의 주요한 객체로 구성된다. DataTableCollecton은 0개 또는 그 이상의 DataTable객체를 포함한다. 그리고 DataTable은 차레로 Columns, Rows, Constraints의 세 개의 컬렉션으로 구성되어 있다. DataRelationCollection은 0개 또는 그 이상의 DataRelation을 포함한다.

DataTable의 Columns 컬렉션은 DataTable을 구성하는 열(Column)을 정의한다. 그리고 ColumnName과 DataType속성, DataColumn의 속성을 사용해서, 널을 허용할 것인지 말 것인지(AllowDBNull)와 최대값의 길이(MaxLength), 그리고 값을 계산하기 위한 수식(Expression)등을 정의할 수 있다.

DataTable의 Rows 컬렉션(비어 있을 수도 있다.)은 Columns 컬렉션으로 정의된 실제 데이터를 포함한다. DataTable은 각 행(Rows)에 대해서 원래 값(original), 현재 값(current)_, 제안된 값(proposed)을 유지한다. 이와 같은 기능으로 인해 프로그래밍 작업이 매우 간단해지는 것을 알게 될 것이다.

DataTable의 Constraints 컬렉션은 0개 또는 1개 이상의 Constraint를 포함한다. 마치 관계형 데이터베이스와 같이, Constraints는 데이터의 무결성을 유지 관리하기 위해 사용된다. ADO.NET은 아래와 같은 두 종류의 제약 조건(Constraint)을 지원한다.

ForeignKeyConstraints : 관계 무결성을 유지한다(즉, 자식 행은 고아가 되지 않는다는 것을 보장)
UniqueConstraints : 데이터 무결성을 유지한다(중복된 행이 테이블에 포함되지 않는다는 것을 보장)

또한 DataTable의 PromaryKey 속성을 이용해서 개체의 무결성을 보장할 수 있다(즉, 각 행의 유일성을 보장한다.)

마지막으로, DataSet의 DataRelationCollection은 0개 또는 그 이상의 DataRelation을 포함한다. DataRelation은 한 테이블의 마스터(부모) 행으로 다른 테이블의 관련 행을 간단히 검색할 수 있도록 프로그램적인 인터페이스를 제공한다. 예를 들어, 주문(Order)이 있다면, DAtaRelation으로 관련된 주문 상세 목록(OrderDetails) 행을 쉽게 뽑아 낼 수 있다. (하지만, DataRelation 그 자체는 관계에 대한 무결성을 보장해 주지 않는다).

Posted by gsi
:

요즘 들어서 복합적으로 프로그래밍 공부를 하고 있지만.
이것저것 테스트를 할려다 보면 항상 걸리는게 DB 쪽인듯 하다.
물론 웹 쪽의 지식 부족으로 아직도 머리속에 있는 생각들을 구현하지 못하고 있지만.

웹을 떠나서 조금은 DB 쪽 부터 탄탄히 잡고 가야 할거 같다.

이것저것 책을 봐도 조금은 내가 알고자 하는 부분을 딱 집어준 책은 없는듯 하다.
우선 "ADO .NET Step by Step" 책을 통해서 조금더 연마하고 다른책도 봐야 할거 같다. ^^

그렇다고 모든걸 다 잡고 가자니 한참 걸릴듯 하고 ..
.Net 부터 시작 한다 생각하고 가보자.

개인 적인 생각은 하나의 프로그래밍을 공부 해서 그것을 먹고 사는 시대는 지났다는 생각이 든다. 수업이 많은 프로그래밍 기법들이 존재 하는 지금 시점에서 다양한 시점에서 여러가지 부분을 다 알고 있어야 살아 남지 않나 생각 한다.

나 자신이 조금더 발전하는 그날까지.. 화이팅 !!!
Posted by gsi
:

msdn expression 주소

내 일상 2007. 9. 15. 11:58 |

http://msdn2.microsoft.com/ko-kr/express

페이지.. ctp 버젼의 툴도 많이 제공 되고.. 공부 하기에 딱.. ^^

http://msdn2.microsoft.com/ko-kr/express/aa718391.aspx

여기는 db 관련 동영상 강좌가 있으니 조금더 봐야 겠다.
Posted by gsi
:

FOR XML 사용방법#1

DB&XML 2007. 9. 14. 16:59 |

상세한 내용은 온라인에 있는 MSDN을 참고 바랍니다.
http://msdn2.microsoft.com/en-us/library/ms345137.aspx


select * from joyboard_notice for xml auto, type;
>> 결과
<joyboard_notice no="1" ... category="" />
<joyboard_notice no="2" ... category="" />


SELECT (SELECT * FROM joyboard_notice FOR XML AUTO, TYPE).query(
'<doc>{
   for $c in /joyboard_notice
   return
     <Person name="{data(
$c/@id)}"/>
 }</doc>')

>> 결과
<doc>
  <Person name="jaeukan" />
  <Person name="usarabia" />
</doc>
>> joyboard_notice : 테이블 이름
>> data($c/@id) : id는 컬럼명

SELECT ID as "@id",
  Nick
FROM joyboard_notice
FOR XML PATH('Customer'), ROOT('doc')

>> 결과
<doc>
  <Customer id="jaeukan">
    <Nick>Azitro</Nick>
  </Customer>
  <Customer id="usarabia">
    <Nick>사라비아</Nick>
  </Customer>
</doc>
Posted by gsi
:

내가 다니고 있는 회사..
내가 일하고 있는 회사..
나로 인해 움직이는 회사..
내가 하고 싶은 꿈을 이룰수 있는 회사..
그런 회사가 여기였음 좋겠네요 ^^.

화이팅!!

사용자 삽입 이미지

▒ iamgsi ▒

Posted by gsi
:

발췌...(inside C#_2E, 무료기술 서적)

FileStream은 바이너리 데이터를 읽거나 쓸 수 있다. 문자 데이터로 작업하려면 StreamReader와 StreamWrite와 같은 클래스가 더 적합하다. 이러한 클래스는 백그라운드에서 FileStream 객체를 사용하여 원본 바이트 처리 과정의 최상위 계층인 문자 삽입 계층에 효과적으로 작동할 것이다. StreamReader/StreamWriter를 닫는 것은 백그라운드에 깔려 있는 FileStream 또한 닫는다는 것을 의미한다.

FileStream s =
    new FileStream("Bar.txt", FileMode.Create);
StreamWriter w = new StreamWriter(s);
w.Write("Hello World");
w.Close();

s = new FileStream("Bar.txt", FileMode.Open);
StreamReader r = new StreamReader(s);
string t;
while ((t = r.ReadLine()) != null)
{
    Console.WriteLine(t);
}
w.Close()

결과 : Hello World

StreamReader 클래스와 StreamWriter 클래스는 Encoding을 사용하여 문자를 바이트로 혹은 그 반대로 변환할 수 있다. 몇몇 엔코딩을 이용하여 데이터를 파일에 기록하려면 다음과 같이 StreamWriter와 Encoding 파라미터를 추가한 StreamReader를 생성해야 한다.

//StreamWriter w = new StreamWriter(s);
StreamWriter w = new StreamWriter(s, System.Text.Encoding.BigEndianUnicode);

[참고]
읽기 전용으로 설정된 파일을 열려면 FileStream 생성자에 파일을 읽기만 하도록 지정하기 위해 몇가지의 파라미터를 더 추가할 수 있다.

s = new FileStream(
   "../../TextFile1.txt",
   FileMode.Open, FileAccess.Read);

[참고]
C#에서 파일 경로를 지정할 때 C#에서의 경로는 C나 C++와 동일하게 백슬래시(\)를 사용하기 때문에, 다음과 같은 3가지 방법 중 선택해서 사용할 수 있다.

s = new FileStream(
   "C:\\temp\\goo.txt", FileMode.Create);
or.
s = new FileStream(
   "C:/temp/goo.txt, FileMode.Create);
or.
s = new FileStream(
   @"C:\temp\goo.txt", FileMode.Create);

이상....

Posted by gsi
:

Thread를 두개를 사용할 경우 하나의 함수를 호출한다고 가정해 보자.
그렇게 되면 다량의 데이터를 효과적으로 여러개의 스레드를 사용해서 처리할 수가 있다.
아래의 예제를 보면 AddItems()를 스레드 두개를 사용해서 처리 되고 있다.
하지만 결과를 보면 100개의 데이터 값만 뿌려지는 것을 알수 있다.

이때 사용하게 되는 것이 lock 구문이다. 이 구문을 사용해서 멀티 스레드에서의
데이터를 안전하게 처리할 수 있다.
lock 에 포함되는 것은 동기화에 처리되어야 할 데이터를 락을 걸어 주게 되는 것으로
여겨진다.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ConsoleApplication4
{
    class Program
    {
        static List<string> list = new List<string>();

        static void Main(string[] args)
        {
            new Thread(AddItems).Start();
            new Thread(AddItems).Start();
        }

        static void AddItems()
        {
            for (int i = 0; i < 100; i++)
                lock (list)
                {
                    string _str = "Item " + list.Count + " ID=" + AppDomain.GetCurrentThreadId();
                    list.Add(_str);
                    Console.WriteLine(_str);
                }
        }
    }
}




 

Posted by gsi
:

사용자 삽입 이미지

[작업 경위]

--xaml 파일--
1. Blend를 사용해서 기본 베이스 제작
   - 해당 경로를 입력 받을 수 있도록 TextBox를 추가
   - 경로 이미지를 가져 오기 위한 Button를 추가
   - 이미지를 보여 주기 위한 ListBox를 추가
2. 템플릿 변경
   - ListBox > StackPanel > TextBlock
                                       Border > Image
     위와 같이 파일 이름과 이미지를 보여 주기 위한 테플릿을 하나 제작하였다.
     이 부분은 상세하게 적지 않는다. (lynda 페이지의 blend 항목에 가면 자세히 나와 있음)
3. 리스트 정보를 저장할 CLR 클래스를 하나 생성한다.
   - Name, Path 정보를 담고 있는 클래스이며, 배열로 사용하기 위해서 ObservableCollection 를 사용하였다.
   - xaml 파일로 클래스 연동시킨다.
     xmlns:c="clr-namespace:GsiImageView" //클래스 네임스페이스 추가
     <Window.Resources>
        <c:PathInfoList x:Key="pathData" /> //를 추가 한다.

--cs 파일--                
1. 스레드를 사용하기 위해서 네임 스페이스 추가
   - using System.Threading;
2. xaml 파일의 버튼 클릭 이벤트를 생성한다.
        private void OnFolderOpenClick(object sender, RoutedEventArgs e)
        {
            Thread loadThread = new Thread(new ThreadStart(DataLoad));
            loadThread.Start();
            Thread.Sleep(1);
        }
3. 스레드에 사용할 함수를 하나 만든다. 이 함수내부에서 폴더 내의 이미지를 읽어서 작업 하도록 한다.
        private void DataLoad()
        {
            .....
        }
4. 메인 스레드의 인스턴스된 객체를 접근 하기 위해서 delegate를 선언한다.
        public delegate void UpdateImage(string _path);
5. Invoke에 사용할 함수를 추가 한다.
        public void UpdateImageList(string _path)
        {
            PathInfoList pathinfolist = (PathInfoList)this.FindResource("pathData");
            pathinfolist.Add(new PathInfo(_path, "none.jpg"));
        }
6. DataLoad() 함수 안에 내용을 추가 한다.
        private void DataLoad()
        {
            //디렉토리 경로 가져 오기
            DirectoryInfo di = new DirectoryInfo(@"D:\WPF_Project\GsiImageView\Image\MaxImageTest");
            try
            {
                if (di.Exists)
                {
                    //경로가 있음
                    foreach (FileInfo fi in di.GetFiles())
                    {
                        //경로를 타고 세부 이미지 이름을 얻어 온다.
                        string path = di.FullName + "\\" + fi.Name;

                        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.DataBind, new UpdateImage(UpdateImageList), path);

                        Thread.Sleep(60);
                    }
                }
                else
                {
                    MessageBox.Show("경로가 확실하지 않습니다.");
                    return;
                }
            }
            catch
            {
                MessageBox.Show("경로가 확실하지 않거나, 비정상 오류 입니다.");
                return;
            }
        }


몇개더 구현되어야할 내용입니다.
1. 경로 입력후 해당 경로에 맞는 이미지 찾아 오기
2. 경로 내부의 서브폴더까지 찾아서 이미지 추가 하는 방법 구현하기
3. ListBox의 그룹별 소트 방법 및 재정렬 방법 구현하기
4. 미리 목록을 얻어 와서 드로잉 하고 세부 이미지 부분만을 여러개의 스레드를 사용해서 구동되는 형태로 구현하기
5. 미정...


<해당 데모>


Posted by gsi
:

WPF를 공부 하면서 무언가 만들어 보는 목적이 없다면 공부에 쉽게 지치게 되고 시간을 허비 하게 되는거 같다.
그래서 시작 하였다. "WPF 프로젝!!" 폴더 안의 카테고리는 데모를 제작해 보면서 공부를 하고 데모를 배포 하며, 다른 사람으로 하여금 사용될 수 있는 것을 목표로 한다.

저작권은 본 IamGsi 플로그에 있으며, 배포 또는 사용하는데 있어서 제약이 없습니다.
수정사항이 있거나 아이디어가 있으신 분은 피드백을 해주시면 감사하겠습니다.
단, 상업적인 목적으로 할때는 연락을 주시면 감사하겠습니다.

[프로그램 소개]
본 프로그램은 해당 폴더에 있는 이미지를 화면에 보여 주는 형식입니다.

Posted by gsi
:

일주일 정도 지나고 나니 심사 끝나고 메일이 날라 오네요.

그리고 우선 검색 부분만 제 3단 레이아웃 쪽 오른쪽에 위치 시켜 놨습니다.
다행이 스킨용 플러그인 부분에 추가 하라는 부분이 있어서 그곳에 샥..

다른건 하다 보니 조금 애매해서 조금은 공부 하고 다시 적용해야 할거 같다.
차근 차근.. 공부 한다 생각하고 해봐야 할거 같다.

Posted by gsi
:

PathInfo.cs
----------------------------
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace GsiImageView
{
    public class PathInfo
    {
        private string _path;
        private string _filename;

        public string Path
        {
            get { return _path; }
            set { _path = value; }
        }

        public string FileName
        {
            get { return _filename; }
            set { _filename = value; }
        }

        public PathInfo(string path, string filename)
        {
            this._path = path;
            this._filename = filename;
        }
    }

    public class PathInfoList : ObservableCollection<PathInfo>
    {
        public PathInfoList()
        {
            //최초 입력
            Add(new PathInfo(@"D:\WPF_Project\GsiImageView\Image\1111.jpg", "1111.jpg"));
            Add(new PathInfo(@"D:\WPF_Project\GsiImageView\Image\2222.jpg", "2222.jpg"));
        }
    }
}

Window1.xaml
-------------------------------
<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:GsiImageView"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:GsiImageView="clr-namespace:GsiImageView"
 x:Class="GsiImageView.Window1"
 x:Name="Window"
 Title="Gsi ImageViewer"
 Width="640" Height="480">

 <Window.Resources>
        <c:PathInfoList x:Key="pathData" />
        <ObjectDataProvider x:Key="PathInfoListDS" d:IsDataSource="True" ObjectType="{x:Type GsiImageView:PathInfoList}"/>
  <DataTemplate x:Key="PathInfoListTemplate">
   <DataTemplate.Resources>
    <Storyboard x:Key="OnLoaded1">
     <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="stackPanel" Storyboard.TargetProperty="(UIElement.Opacity)">
      <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.1"/>
      <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
     </DoubleAnimationUsingKeyFrames>
    </Storyboard>
   </DataTemplate.Resources>
   <StackPanel HorizontalAlignment="Stretch" Margin="0,2,2,2" x:Name="stackPanel" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5">
    <StackPanel.Background>
     <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
      <GradientStop Color="#FFA1A1A1" Offset="0"/>
      <GradientStop Color="#FFFFFFFF" Offset="1"/>
     </LinearGradientBrush>
    </StackPanel.Background>
    <StackPanel.RenderTransform>
     <TransformGroup>
      <ScaleTransform ScaleX="1" ScaleY="1"/>
      <SkewTransform AngleX="0" AngleY="0"/>
      <RotateTransform Angle="0"/>
      <TranslateTransform X="0" Y="0"/>
     </TransformGroup>
    </StackPanel.RenderTransform>
    <TextBlock HorizontalAlignment="Stretch" Margin="0,2,0,2" VerticalAlignment="Stretch" Padding="4,0,0,0" Text="{Binding Path=FileName}"/>
    <Border Height="Auto" BorderBrush="#FFCFD6FF" BorderThickness="2,2,2,2" Width="{Binding ElementName=Slider_ImageSize, Path=Value}">
     <Image Width="Auto" Height="Auto" Source="{Binding Path=Path}"/>
    </Border>
   </StackPanel>
   <DataTemplate.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded" SourceName="stackPanel">
     <BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
    </EventTrigger>
   </DataTemplate.Triggers>
  </DataTemplate>
  <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
   <WrapPanel/>
  </ItemsPanelTemplate>
 </Window.Resources>

 <Window.Background>
  <LinearGradientBrush EndPoint="0.988,0.988" StartPoint="0.008,0.054">
   <GradientStop Color="#FFB5B5B5" Offset="0"/>
   <GradientStop Color="#FFFFFFFF" Offset="1"/>
  </LinearGradientBrush>
 </Window.Background>

 <Grid x:Name="LayoutRoot">
  <Grid.RowDefinitions>
   <RowDefinition Height="30.192"/>
   <RowDefinition Height="*"/>
  </Grid.RowDefinitions>
  <Label HorizontalContentAlignment="Center" Padding="0,0,0,0" VerticalContentAlignment="Center" HorizontalAlignment="Left" Margin="0,0,0,0" Width="43" Content="경로 :"/>
  <TextBox Background="{x:Null}" BorderBrush="#7F939393" BorderThickness="2,2,2,2" HorizontalContentAlignment="Left" Padding="0,1,0,1" VerticalContentAlignment="Center" Margin="43,0,0,0" x:Name="DirBox" Text="TextBox" TextWrapping="Wrap" HorizontalAlignment="Left" Width="59"/>
  <Button HorizontalAlignment="Right" Margin="0,0,0,0" x:Name="FolderOpen" Width="63" Content="테스트" Click="OnFolderOpenClick"/>
  <ListBox IsSynchronizedWithCurrentItem="True" Background="{x:Null}" Margin="4,4,4,4" x:Name="ImgListBox" Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{DynamicResource PathInfoListTemplate}" ItemsPanel="{DynamicResource ItemsPanelTemplate1}" ItemsSource="{Binding Mode=OneWay, Source={StaticResource pathData}}"/>
  <Slider Margin="109,0,70,0" x:Name="Slider_ImageSize" VerticalAlignment="Center" Maximum="1024" Minimum="10" Value="100"/>
 </Grid>
</Window>

Window1.xaml.cs
-----------------------------
using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Threading;

namespace GsiImageView
{
 public partial class Window1
 {
        public delegate void UpdateImage(string _path);

  public Window1()
  {
   this.InitializeComponent();
   
   // Insert code required on object creation below this point.

            //ObjectDataProvider dp = (ObjectDataProvider)this.FindResource("PathInfoListDS");
            //pathInfolist = (PathInfoList)dp.Data;
  }

        private void OnFolderOpenClick(object sender, RoutedEventArgs e)
        {
            //ImgListBox.Items.Add(new PathInfo(@"D:\WPF_Project\GsiImageView\Image\3333.jpg", "3333.jpg"));

            //Window1 w1 = new Window1();
            Thread loadThread = new Thread(new ThreadStart(DataLoad));
            loadThread.Start();
            Thread.Sleep(1);
        }

        private void DataLoad()
        {
            //디렉토리 경로 가져 오기
            DirectoryInfo di = new DirectoryInfo(@"D:\WPF_Project\GsiImageView\Image\MaxImageTest");
            try
            {
                if (di.Exists)
                {
                    //경로가 있음
                    foreach (FileInfo fi in di.GetFiles())
                    {
                        //경로를 타고 세부 이미지 이름을 얻어 온다.
                        string path = di.FullName + "\\" + fi.Name;
                        //il.Add(new PathInfo(path, fi.Name));

                        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.DataBind, new UpdateImage(UpdateImageList), path);

                        Thread.Sleep(60);
                    }
                }
                else
                {
                    MessageBox.Show("경로가 확실하지 않습니다.");
                    return;
                }
            }
            catch
            {
                MessageBox.Show("경로가 확실하지 않거나, 비정상 오류 입니다.");
                return;
            }
        }

        public void UpdateImageList(string _path)
        {
            PathInfoList pathinfolist = (PathInfoList)this.FindResource("pathData");
            pathinfolist.Add(new PathInfo(_path, "none.jpg"));
//            Thread.Sleep(1);
/*
            //pathInfolist.Add(new PathInfo(_path, "none"));
            ImgListBox.Items.Add(new PathInfo(_path, "none"));
            ImgListBox.UpdateLayout();
            try
            {
                int iii = 0;
            }
            catch(Exception e)
            {
                int iii = 0;
            }
 */
        }
 }
}

Posted by gsi
:

멀티 스레드.. 정리..

C# 2007. 9. 12. 12:59 |

메세지큐에 모든 동작 상태들을 담게 된다.
그리고 그 내용을 메인 스레드에서 실제로 작업 해도 담당하게 된다.

하지만 여기서 다른 스레드와의 동기 여부가 문제가 되며,
다른 스레드에서는 메인스레드에서 생성된 인스턴스된 객체들에 바로 제어를 하지 못한다.

그래서 다른 스레드에서 하는 작업을 메세지 큐에 집어 넣고 메인 스레드가 작업은 해야 한다.
그렇기 때문에 여기서 나오는 내용들이
Invoke, BeginInvoke 가 나오게 된다.

Invoke 해당 내용이 업데이트 될때까지 기다렸다가 다음 행을 시작하게 되며,
BeginInvoke 비동기 적으로 바로 다음 행으로 진행이 되며, 나중에 업데이트가 되게 된다.

...

메인 스레드에게 이러한 작업을 실행해라 하고 다른 스레드에서 위임을 시켜 줘야 한다.

//핸들러 설정
public delegate void UpdateUIHandler(DataSet _dsTmp);

public void GetTable()
{
   Console.Write(...);
   string SQLCommentText = ...
   ....
   Thread.Sleep(1000 * 5);

   //TargetGrid가 태어난 스레드에서 실행을 하게 된다.
   TargetGrid.Invoke(new UpdateUIHandler(UpdateUI), new object[] {_dsTmp});
}

public void UpdateUI(DataSet _dsTmp)
{
   TargetGrid.DataSource = _dsTmp.Tables[0];
}

실행을 하게 되면
내가 다르게 만든 스레드에서 UpdateUI를 하게 되지만 UpdateUI는 메인 스레드에서
작업 하게 된다.

윈도우 어플리케이션에서는 스레드를 사용하지만 다른 스레드에서 사용하지 않고
메인 스레드로 위임 해서 꼭 사용해야 한다.
이럴때 사용하는게 Invoke()가 된다.

BeginInvoke를 Invoke를 사용하게 되면
다음 행은 바로 실행 되고, UpdateUI를 실행하는 스레드는 따로 진행하게 된다.

Posted by gsi
:

공도님이 소개해준 스레드 강좌.. 좋네욤.. 7편까지 있음..
http://vismuri.com/blog_category_12.aspx
Posted by gsi
: