2017년 3월 2일 목요일

[국비지원교육/IT실무학원/구로IT학원/C#/ADO.NET/자마린교육추천_탑크리에듀](자마린교육,네비게이션을위한 네비게이션스택에 푸시,화면전환)Pushing Pages to the Navig

(자마린교육,네비게이션을위한 네비게이션스택에 푸시,화면전환)Pushing Pages to the Navigation Stack 

Hierarchical Navigation
n  로그인 NavigationPage 클래스는 사용자들이 앞뒤로 계층적인 page 네비게이션을 할 수 있도록 지원하는데 Page 객체의 Stack(LiFo 구조)을 구현했다.
n  한 페이지에서 다른 페이지로 이동하기 위해서 Navigation Stack에 푸시하면 되고 이 전 페이지로 돌아가기 위해서는 응용프로그램은 Navigation Stack에서 현재 페이지를 Pop하면 된다.


n  계층적인 네비게이션에서 NavigationPage 클래스는 ContentPage 객체의 스택을 통해 탐색을 하는데 모든 플랫폼에서 Page.Title 속성으로 페이지 상단 타이틀을 표시한다.


n  루트 페이지 생성하기

맨 처음 페이지는 App.cs의 다음 코드를 통해 생성되는데 Page1Xaml ContentPage의 인스턴스가 Navigation Stack의 상단에 푸시되면서 현재의 활성화된 페이지가 되고 또한 현재 응용프로그램의 Root 페이지가 된다.

참고로 Xamarin.Forms 응용프로그램에서 계층적인 네비게이션을 수행하기 위해서 NavigationPage의 모든 인스턴스는 ContentPage 인스턴스가 되어야 한다.

public App ()
{
  MainPage = new NavigationPage (new Page1Xaml ());
}



Page2Xaml 페이지를 탐색하기 위해서는 현재 페이지 Navigation 속성의 PushAsync 메소드를 통해 Page2Xaml 인스턴스가 전달되어야 한다.

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
// Page2Xaml 페이지가 스택의 상단에 푸시되면서 Active Page가 된다.
await Navigation.PushAsync (new Page2Xaml ());
}

// PushAsync 메소드가 호출되면 두개의 이벤트가 발생되는데
// 현재 페이지는 OnDisappearing, 호출되는 페이지는 OnAppearing 이벤트가 발생한다.
// 두 이벤트가 발생된 후 PushAsync Task가 종료된다.
// 두 이벤트는 별로 이점이 없는데 iOS에서 OnDisappearing 이벤트는
// 응용프로그램이 종료될 때 호출된다.



Active Page는 디바이스 또는 스크린의 Back 버튼을 이용해서 Navigation Stack에서 Pop될 수 있는데 프로그래밍적으로 원래 페이지로 돌아가기 위해서 Page2Xaml 인스턴스는 PopAsunc 메소드에 의해 호출되어야 한다.


// 아래 코드에 의해 Page2Xaml 인스턴스는 스택의 상단에서 Pop되고
// 이전의 Page1Xaml 인스턴스가 Active Page가 된다.
// PopAsync 메소드가 호출되면 두개의 이벤트가 발생되는데
// 현재 Pop 되는 페이지는 OnDisappearing, 스택의 상단으로 올라오는 리턴되는
// 페이지는 OnAppearing 이벤트가 발생한다그다음 PopAsync Task가 종료된다.
async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopAsync ();
}

n  Navigation 프로퍼티의 PushAsync 및 PopAsync 메소드는 Root 페이지를 제외한 모든 페이지를 Pop 시키기 위해 PopToRootAsync 메소드를 제공하는데 다음 예문을 보자.

async void OnRootPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopToRootAsync ();
}


[국비지원교육/IT실무학원/구로IT학원/C#/ADO.NET/자마린교육추천_탑크리에듀][강좌#13]C#에서의 Thread

쓰레드(Thread) 
쓰레드란 CPU를 이용하는 가장 작은 단위인데 싱글 쓰레드를 사용하면 CPU의 사용 권한을 하나의 쓰레드가 독차지 하게 된다. 지하철 개찰구의 예를들면 개찰구가 하나라면 평상시에는 큰 무리가 아니지만 출퇴근 시간에는 무리가 따를 수 있다. 결국 개찰구를 늘여야 한다는 것이다. 프로그래밍에서 볼 때 개찰구를 늘이는 것이 멀티 쓰레드를 이용하는 것이다. 멀티 쓰레드가 제대로 동작하기 위해서는 CPU가 여러 개 있어야 한다. 보통은 단일 CPU를 사용 할 것이다. CPU는 한번에 하나의 쓰레드를 사용하므로 멀티 쓰레드 프로그램이 실행되는 경우에는 CPU의 사용 시간을 나누어서 각각의 쓰레드에게 나누어 주는 것이다. 결국 개찰구는 늘였지만 표를 파는 곳은 한 군데 인것이다. 

C#에서의 멀티 쓰레드 

C#에서 멀티 쓰레드를 사용하는 방법은 기 정의된 쓰레드 클래스를 사용하면 된다. 결국 배워야 하는 것은 C#에서 멀티 쓰레드를 위한 클래스가 어떤 것이 있고 그 사용법은 어떻게 되는가 이다. 쓰레드를 위한 개체들은 System.Threading 네임스페이스 안에 정의 되어 있다. 

[첫번째 예제] 
using System; 
using System.Threading; 

public class ThreadTest 

public void FirstWork() 

for(int i=0; i < 100; i++) 

Thread.Sleep(1000); //밀리세컨드 단위 
Console.Write("F{0} " ,i); 



public void SecondWork() 

for(int i=0; i < 100; i++) 

Thread.Sleep(1000); 
Console.Write("S{0} " ,i); 



[MTAThread] 
public static void Main() 

ThreadTest t = new ThreadTest(); 

//Thread는 생성자에 ThreadStart형 Delegate를 인자로 받는다. 
Thread first = new Thread(new ThreadStart(t.FirstWork)); 
Thread second = new Thread(new ThreadStart(t.SecondWork)); 

first.Start(); 
second.Start(); 



[예제1-1] 
using System; 
using System.Threading; 
class ThreadTest 

static void Thmethod() 

int id = AppDomain.GetCurrentThreadId(); 
Console.WriteLine("Thread[{0}] Thmethod Method Running",id); 

static void Main() 

int id = AppDomain.GetCurrentThreadId(); 
Console.WriteLine("Main Thread[{0}]",id); 
for(int i=0;i<10;i++) 

Thread th = new Thread(new ThreadStart(Thmethod)); 
th.Start(); 





Thread.Sleep 안에는 해당 Thread가 얼마만큼 쉴 건지에 대한 시간을 밀리 세컨드단위로 지정 한다. 만약 시간을 0으로 설정하면 현재 자신에게 주어진 시간을 다른 쓰레드에게 쓰게 하겠다는 의미이다. 지금 당장은 CPU를 사용 하지 않아도 될 때 다른 쓰레드에게 CPU를 사용 할 기회를 줌으로써 CPU를 효율적으로 이용 할 수 있다. 쓰레드를 쉐게 하는 방법은 Thread.Suspend 를 이용 할 수도 있다. Sleep과의 차이는 Sleep인 경우엔 지정한 시간 만큼 쉰다는 의미지만 Suspend인 경우엔 Resume 메소드를 호출 할 때 까지 쉬게 된다는 것이다.또 다른 차이점은 Sleep 메소드는 자기 자신의 쓰레드만 쉬게 할 수 있다. 반면에 Suspend 는 자기 뿐 아니라 다른 쓰레드도 쉬게 할 수 있다.잠을 자고 있는 Thread가 스스로 깰 수는 없다. 그래서 Suspend로 쉬고 있는 쓰레드는 다른 쓰레드가 Resume을 이용하여 깨울 때 까지 쉬고 있는 것이다. 주의 할 점은 Sleep인 경우는 쓰레드가 즉시 중단 되지만 Suspend로 쉬게 할려면 즉시 중단 되지 않는다. 

[예제2] 
using System; 
using System.Threading; 

public class ThreadTest2 

public bool sleep = false; 
public void FirstWork() 

for(int i=0; i < 10; i++) 

Console.WriteLine("F{0}", i); 
if (i == 5) 

sleep = true; 
Console.WriteLine(""); 
Console.WriteLine("first 쉼..."); 
Thread.CurrentThread.Suspend(); 





class TestMain 

[MTAThread] 
public static void Main() 

ThreadTest2 t = new ThreadTest2(); 
Thread first = new Thread(new ThreadStart(t.FirstWork)); 

first.Start(); 

while(t.sleep == false) {} 

Console.WriteLine(""); 
Console.WriteLine("first를 깨웁니다..."); 
first.Resume(); 


Suspend 메소드로 쓰레드를 잠시 중지하면 Resume 메소드로 다시 동작하게 할 수 있지만 Thread.Abort로 일단 쓰레드를 종료 시키면 다시 되살릴 수 없다.쓰레드가 확실히 종료 되었는지를 살펴보기 위해서는 Thead.Join 메소드를 사용 할 수 있는데 Thread.Join 메소드는 동기적으로 동작하므로 쓰레드가 종료 할 때까지 기다리게 된다. 만일 어떤 이유에서든지 쓰레드가 종료 되지 않는 다면 무한정 기다릴 수 밖에 없다. Thread.Join 메소드 안에 1/1000초 단위로 파라미터를 전달 할 수 있는데이것은 얼마 만큼 Join으로 붙은 쓰레드가 종료 될 때까지 기다릴 수 있는 가에 대한 값이다. 만일 주어진 시간안에 종료되면 true를 반환하고 기다리기를 중지 한다면 false 값을 반환 한다. 

쓰레드가 여러 개 있다면 한 쓰레드가 동작하고 나서 어떤 쓰레드가 동작 할까? 아마도 높은 우선 순위를 가지고 있는 쓰레드가 수행 될 것이다. 각각의 쓰레드는 CPU 사용 권한에 대한 우선 순위가 있는데 우선 순위가 높을수록 CPU사용 권한을 먼저 할당 받는다. 

아래의 예제를 보도록 하자. 

using System; 
using System.Threading; 

public class ThreadTest3 

public bool sleep = false; 
public void FirstWork() 

for(int i=0; i < 10; i++) 

for(int j=0; j < 10; j++) 

Thread.Sleep(100); 
Console.Write(","); 


Console.WriteLine("F{0}", i); 



public void SecondWork() 

for(int i=0; i < 10; i++) 

for(int j=0; j < 10; j++) 

Thread.Sleep(100); 
Console.Write(","); 


Console.WriteLine("S{0}", i); 




class TestMain 

[MTAThread] 
public static void Main() 

ThreadTest3 t = new ThreadTest3(); 
Thread first = new Thread(new ThreadStart(t.FirstWork)); 
Thread second = new Thread(new ThreadStart(t.SecondWork)); 

first.Start(); 
second.Start(); 



위의 예제를 실행해 보면 각각의 쓰레드가 할당 받은 시간이 비슷함을 알 수 있다. 두개의 쓰레드가 우선 순위가 비슷 하니까 아래의 그림과 같은 결과가 나오는 것이다. 

Thread1.jpg

아래의 예는 Join을 이용한 예제이다. 
first.Join() 부분을 주석으로 막은 후 다시 실행 해 보라. 

using System; 
using System.Threading; 

public class ThreadTest2 

public int[] iArray = new int[100]; 
public void CollectData() 

for(int i=0; i <= 20; i++) 

iArray[i] = i+1; 
Console.Write(","); 
Thread.Sleep(500); 




class TestMain 

[MTAThread] 
public static void Main() 

ThreadTest2 t = new ThreadTest2(); 
Thread first = new Thread(new ThreadStart(t.CollectData)); 

first.Start(); 
first.Join(); 

int sum=0; 
for(int i=0; i { 
sum += t.iArray[i]; 


Console.WriteLine(); 
Console.WriteLine("sum = {0}", sum); 




한 쓰레드에 대해 우선순위를 높여 주면 CPU 사용 권한을 우선적으로 갖는 것이다. Thread의 우선 순위와 관련된 프로퍼티가 있는데 열거형 값인 Highest, AboveNormal, Normal, BelowNormal, Lowest중 한 값이다. 아래의 예제를 살펴 보자. 


using System; 
using System.Threading; 

public class ThreadTest3 

public bool sleep = false; 
public void FirstWork() 

for(int i=0; i < 10; i++) 

for(int j=0; j < 10; j++) 

Thread.Sleep(100); 
Console.Write(","); 


Console.WriteLine("F{0}", i); 



public void SecondWork() 

for(int i=0; i < 10; i++) 

for(int j=0; j < 10; j++) 

Thread.Sleep(100); 
Console.Write(","); 


Console.WriteLine("S{0}", i); 




class TestMain 

[MTAThread] 
public static void Main() 

ThreadTest3 t = new ThreadTest3(); 
Thread first = new Thread(new ThreadStart(t.FirstWork)); 
Thread second = new Thread(new ThreadStart(t.SecondWork)); 

first.Priority = ThreadPriority.Lowest; 

first.Start(); 
second.Start(); 



Thread2.jpg

멀티쓰레드 환경인 경우 여러 곳에서 같은 객체의 메소드를 호출 하는 경우에 예기치 않은 결과가 나타날 수 있다. 어떤 메소드의 사용을 한 쓰레드가 끝난 후 다른 쓰레드가 접근하게 하려면 lock 문을 사용 한다. 다음의 예제를 보도록 하자. 


using System; 
using System.Threading; 

public class ThreadTest3 

public string lockString = "Hello"; 
public void Print(string rank) 

//lock을 걸어준 구문은 처음 쓰레드가 끝날때 까지 다른 쓰레드가 접근 금지 
lock (this) 

for(int i=0; i < 10; i++) 

for(int j=0; j < 10; j++) 

Thread.Sleep(100); 
Console.Write(","); 


Console.WriteLine("{0}{1} ", rank, lockString); 




public void FirstWork() 

Print("F"); 


public void SecondWork() 

Print("S"); 



class TestMain 

[MTAThread] 
public static void Main() 

ThreadTest3 t = new ThreadTest3(); 
Thread first = new Thread(new ThreadStart(t.FirstWork)); 
Thread second = new Thread(new ThreadStart(t.SecondWork)); 

first.Start(); 
second.Start(); 




lock 문 이외에 System.Monitor라는 클래스가 있는데 이 Monitor 클래스에는 Enter,Exit 메소드가 있는데 Enter 메소드는 잠금 상황으로, Exit 메소드는 잠금을 해제하는 역할을 한다. 앞에서 작성한 예제를 System.Monitor를 이용하는 예문으로 바꿔 보자… 

using System; 
using System.Threading; 

public class ThreadTest3 

public string lockString = "Hello"; 
public void Print(string rank) 

//lock을 걸어준 구문은 처음 쓰레드가 끝날때 까지 다른 쓰레드가 접근 금지 
Monitor.Enter(this); 
for(int i=0; i < 10; i++) 

for(int j=0; j < 10; j++) 

Thread.Sleep(100); 
Console.Write(","); 


Console.WriteLine("{0}{1} ", rank, lockString); 

Monitor.Exit(this); 


public void FirstWork() 

Print("F"); 


public void SecondWork() 

Print("S"); 



class TestMain 

[MTAThread] 
public static void Main() 

ThreadTest3 t = new ThreadTest3(); 
Thread first = new Thread(new ThreadStart(t.FirstWork)); 
Thread second = new Thread(new ThreadStart(t.SecondWork)); 

first.Start(); 
second.Start();