'thread'에 해당되는 글 1건

  1. 2008.04.08 쓰레드에 의한 파일 전송 1

쓰레드에 의한 파일 전송

Program/SilverLite | WPF 2008. 4. 8. 09:48

쓰레드에 의한 파일 전송

환경 : VS2008, WPF 프로젝트


내용 : 쓰레드를 사용하여 내트워크 내의 원격지에 파일을 전송한다.
파일 전송 상황에 대한 ProgressBar를 갱신한다.


파일 전송
우선 알아야 할것은 파일의 전송량의 정보를 어떻게 알 것인가 이다.
FileStream 클래스를 이용해 보자

사용자 삽입 이미지

여기서 Info는 개인적으로 정의한 구조체로 복사 원본 파일명과 대상 경로를 가지고 있다.
두개의 파일 스트림을 정의하고, 버퍼를 생성한다.
버퍼의 단위만큼 파일을 기록하고 이 정보를 통해 현재 진행 상황을 알 수 있을 것이다.

사용자 삽입 이미지

좀 더 꼼꼼한 개발자라면 Try Catch Finally를 통해 오류 상황에 대한 처리를 잊지 않을 것이다.
사용자 삽입 이미지


왜 쓰레드를 사용하였는가?
용량이 큰 파일을 전송해보았다면, 해당 응용프로그램은 정지 상태가 된다.
이 시점에서 UI의 변경이나 다른 작업을 시도한다면, 응용프로그램은 응답없음 상태가 될 것이다.
이후에 설명하겠지만 Progressbar에 작업 상황을 표현 하는 것 또한 쉽지 않을 것이다.

쓰레드를 사용하기 위해서 우선, 쓰레드에 대한 이해가 필요하다.
쓰레드를 사용함으로서 생기는 문제점들에 대해서 고려되어야 할 것이다.

다음 글은 네이버 블로그 muduri07님의 포스트에 이해 대한 자료가 잘 정리되어 있다
http://blog.naver.com/muduri07?Redirect=Log&logNo=130006369226
다른 주의 사항들과 비롯하여 쓰레드는 최소단위의 오퍼레이션이어야 한다는 것을
명심하기 바랍니다.

쓰레드에 대한 이해가 되었다면 다음으로 WPF 에서의 쓰레드에 대한 이해가 필요하다.
MSDN "발송자를 사용하여 응답 성능이 뛰어난 응용 프로그램 작성" 이라는 포스트이다.
http://msdn2.microsoft.com/ko-kr/magazine/cc163328.aspx

내용을 요약하자면, UI들은  DispatcherObject 를 상속받아 Dispatcher(발송자)를 보유하고 있다.
이러한 발송자들은 메세지 처리 및 기타의 작업들을 진행하는 역할을 한다.
이러한 역할이 VerifyAccess, CheckAccess 다.
DispatcherObject 를 상속받은 개체는 UI쓰레드가 아닌 곳에서 호출될때 에러를 발생한다.
발송자의 Invoke, BeginInvoke 매서드를 통해서 이 상황을 해결한다.
또한 BackgroundWorker를 이용할 수 있다.

한마디로 UI 개체들은 자신이 속한 쓰레드가 아닌 다른 쓰레드 에서 호출할때 에러가 발생하고, 이 문제를 해결하기 위한 방법에 대한 포스트 이다.

실제 적으로 쓰레드를 생성하는 것은 간단하다.
이 둘의 네임스페이스가 필요 할 것이다.

using System.Windows.Threading;
using System.Threading;

Thread trd = new Thread(new ThreadStart(FileCopyThread));
trd.Start();

Thread 클래스는 생성자 파라미터로 ThreadStart 라는 대리자(delegate)를 요한다.
쓰레드의 사용에서 대리자는 실과 바늘과 같은 관계로서 쓰레드의 진입 시점이 되는 매서드를 제공한다.
대라자는 과거 C의 경우의 매서드 포인터와 같은 개념으로 이해하고 있다.
매서드를 지칭하고 있는 대리자는 대리자의 사용으로 매서드를 호출한다.

위 코드는 ThreadStart라는 대리자를 통해 FileCopyThread 라는 매서드를 호출 하고 있고,
ThreadStart 는 프레임 워크에서 제공되는 대리자 이다.

FileCopyThread 매서드는 앞부분에서 설명한 파일의 복사 작업을 진행하게 될 것이다.

지금까지 내용을 살펴 보면 쓰레드를 생성하였고, 이러한 쓰레드를 통해 파일 전송을 진행한다.
다음으로 보아야 할 것은 파일 전송 상황에 대한 ProgressBar의 갱신이다.

ProgressBar의 갱신 또한 스레드로 처리되어야 한다.
파일의 전송과 ProgressBar의 갱신이 같은 스레드내에 존재한다면..
파일이 전송되는 도중에는 Progressbar를 갱신하지 못할 것이기 때문이다.
하지만 이 문제에 대한 해결은 앞부분에 설명하였다.
사용자 삽입 이미지

FilecopyThread 매서드에 대해 살펴보자
Dispatcher.Invoke(DispatcherPriority.Normal, _pgsSetting, (int)(SourceFile.Length / BUFFER));
Invoke 매서드는 우선순위, 대리자, 대라자에 전달된 파라미터 들을 인자로 가진다.
이 매서드는 _pgsSetting 라는 대리자를 호출하여 int 값을 파라미터로 전달 하고 있다.

_pgsSeetting 라는 대리자를 정의 하는 부분이다.

delegate void DG_SetProgress(int max);
private void SetProgress(int max)
{
progressFile.Value = 0;
progressFile.Minimum = 0;
progressFile.Maximum = max;
}

_pgsSetting = new DG_SetProgress(SetProgress);

SetProgress 매서드는 progressFile 이라는 프로그레스바를 호출하고있다.
아래는 프로그래스바의 상태를 갱신하는 부분이다.
DG_RefreshProgress _pgsRefresh;
private void RefreshProgress()
        {
            progressFile.Value += 1;
            progressTotal.Value += 1;
        }

이렇게 Invoke 매서드를 통해 새로운 스레드에서 프로그래스의 값을 변경한다.

지금가지의 내용을 요약한다면 메인 윈도우에는 프로그레스 바가 놓여있다.
파일을 전송 명령이 시작되면 스레드를 통해 파일의 전송이 진행된다.
이 스레드는 파일 전송도중 진행상황을 메인 윈도우의 프로그레스 바에 표현 하는데,
Dispatcher.Invoke 매서드를 통해 새로운 스레드로서 동작하게 된다.

'Program > SilverLite | WPF' 카테고리의 다른 글

Resource Dictionary  (0) 2008.04.01
폴더/ 디렉토리 탐색기/브라부져 FolderBrowser  (0) 2008.04.01
SilverLite  (0) 2008.01.16
: