'2018/11'에 해당되는 글 3건

Programming/.NET

비트 단위의 논리 연산을 수행합니다.

 

int i = 10;

int bit_and = i & 3;
int bit_or = i | 3;
int bit_xor = i ^ 3;
int bit_not = ~i;

Console.WriteLine("Result : {0} | {1}", bit_xor, bit_not);

 

& 는 and 연산으로서 같은 값인것만 1로 처리합니다. 그래서 10의 값이 1010과 3의 값인 0011을 연산하면

 

1010
0011
----
0010

 

이 되어 결과는 3이 됩니다.

 

| 는 or 연산입니다. 따라서 둘중 어느 하나라도 1이 있으면 결과는 1이 됩니다.

 

1010
0011
----
1011

 

^ 는 Xor 연산으로 둘의 값이 1이든 0이든 서로 틀려야만 1이 됩니다.

 

1010
0011
----
1001

 

마지막으로 ~는 보수입니다. 피연산자의 모든 값을 반대로 뒤집습니다.

 

1010
----
0101

 

다만 이 경우 부호를 나타내는 최상위 비트도 반대로 처리하기 때문에 결과는 -값이 됩니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET MVC] Razor  (0) 2019.01.08
[ASP.NET MVC] URL 다루기  (0) 2018.12.18
[C#] 비트(bit) 연산자  (0) 2018.11.20
[ASP.NET MVC] 액션 메서드(Action Method)  (0) 2018.11.13
[C#] Thread  (0) 2018.11.06
[C#] MemoryStream / StreamWriter / StreamReader / BinaryWriter / BinaryReader  (0) 2018.10.31
0 0
Programming/.NET

사용자가 요청한 URL에 따라 컨트롤러 내부에 해당하는 액션메서드(Action Method)를 찾아 사용자에게 보여줍니다.

 

public ActionResult Index()
{
    return View();
}

 

액션메서드를 기본적으로 같은 이름의 뷰를 찾기 때문에 액션 메서드가 Index라면 Index.cshtml과 같은 뷰를 렌더하게 됩니다.

 

[ActionName("myIndex")]
public ActionResult MyPage()
{
    return View("MyPage");
}

 

액션 메서드에 ActionName 속성을 사용하게 되면 설정 값에 따라 액션메서드 이름을 재정의하게 됩니다. 따라서 위 예제에서는 MyIndex로 접근시 MyPage 액션메서드를 실행하게 됩니다. 다만 MyIndex로 요청을 받으면 뷰도 기본적으로 MyIndex뷰를 찾게 되므로 MyIndex라는 뷰를 따로 생성하거나 아니면 View 메서드를 호출할때 보여줄 수 있는 다른 뷰를 설정하는 방법으로 적절히 대처해야 합니다.

 

public ActionResult MyPage()
{
    return View();
}

[HttpPost]
public ActionResult MyPage(string idstring name)
{
    return View();
}

 

같은 이름의 액션메서드라도 요청방식에 따라 다른 액션메서드가 호출될 수 있도록 할 수 있습니다. 예제에서는 [HttpPost] 속성을 설정해 두번째 MyPage 액션 메서드는 Post요청에만 응답할 수 있도록 하고 있습니다. 이 외에도 HttpGet이나 HttpPut과 같은 속성을 설정할 수 있습니다.

 

[NonAction]
public ActionResult MyPage(string idstring name)
{
    return View();
}

 

NonAction 속성은 해당 메서드가 액션 메서드로서 인식될 수 없도록 합니다.

 

만약 요청으로 들어온 URL에서 어떤 액션 메서드를 반환해야 할지 찾을 수 없으면 MVC 프레임워크는 기본적으로 HTTP 404 오류를 반환합니다. 하지만 HandleUnknownAction 메서드를 재정의하면 알 수 없는 요청에 대해 다른 대체적인 방법으로 다음과 같이 처리할 수 있습니다.

 

protected override void HandleUnknownAction(string actionName)
{
    Response.Write("Error!!");
}

0 0
Programming/.NET

실행중인 프로그램은 하나의 프로세스로 볼 수 있고 프로세스는 시작될때 기본적으로 하나의 스레드를 생성하게 됩니다. 스레드가 없는 프로세스는 존재하지 않습니다. 프로세스가 무엇인가 작업을 수행하려면 반드시 해당 작업을 수행하는 스레드를 생성해야 합니다. 스레드는 프로세스의 작업단위입니다. 예를 들어 사용자로부터 특정값을 입력받아 합계를 계산하는 아래와 같은 프로그램이 있습니다.

 

static void Main(string[] args)
{
    Console.Write("첫번째 값 : ");
    string i = Console.ReadLine();

    Console.Write("두번째 값 : ");
    string j = Console.ReadLine();

    int sum = int.Parse(i) + int.Parse(j);

    Console.WriteLine("결과 : {0}", sum);

    Console.Read();
}

 

이 프로그램은 입력과 계산, 결과출력에 대한 일련의 작업이 main 메서드에 정의되어 있고 따라서 메서드 실행을 위한 스레드를 생성해야 하는 것입니다. 프로세스는 반드시 하나이상의 스레드를 생성하며 기본적으로 생성되는 최초의 스레드를 주 스레드(main thread)라고 합니다.

 

CPU는 각 프로세스마다 생성한 스레드를 하나씩 돌아가며 실행합니다. 물론 단일 CPU는 하나의 스레드만을 실행할 수 있었지만 내부에 4코어, 8코어처럼 멀티코어를 가진 CPU라면 코어수만큼의 여러 스레드를 동시에 실행할 수도 있을 것입니다. 만약 4코어라면 4개의 스레드를 동시에 순회하면서 실행하는 것이 가능합니다.  그러나 일반적으로 CPU가 실행해야할 스레드의 수는 수십개나 그 이상이기에 모든 스레드를 동시에 실행할 수는 없습니다. 4개나 8개의 스레드를 동시에 실행한다고 하더라도 이들 스레드를 실행한 뒤 종료될때까지 기다릴 수 없기에 시간을 조금씩 할당해서 대기중인 각 스레드를 모두 돌아가며 실행해야 합니다.

 

스레드안에는 CPU가 읽어 실행될 명령어집합이 존재하는데 이를 스레드문맥(thread context)이라고 합니다. 메서드로 비유하자면 메서드의 시작부터 마지막까지 작성된 일련의 코드에 해당하는 것입니다. CPU는 스레드의 문맥을 읽어 실행하다가 다른 스레드를 실행하기 직전에 현재 실행중인 스레드의 상태를 스레드문맥에 저장합니다. 그런뒤 다른 스레드로 실행을 이동하게 되는데, 현재상태를 문맥에 저장해야 하는 이유는 스레드의 실행계획이 담긴 스케쥴링에 따라 CPU가 다시 해당 스레드를 실행할때 이전에 저장된 상태를 스레드문맥으로부터 읽어들여서 마치 이전부터 계속 실행중이었던것처럼 스레드의 실행을 이어나갈 수 있기 때문입니다.

 

Thread는 기본적으로 현재 실행중인 스레드에 접근할 수 있는 몇가지 속성을 제공하며 필요한 경우 새로운 새로운 스레드를 생성할 수도 있습니다.

 

static void Main(string[] args)
{
    Thread t = new Thread(myThread);
    t.Start();

    Console.Read();
}

static void myThread()
{
    Console.WriteLine("hahaha");
}

 

스레드를 생성할때는 스레드를 통해 실행할 메서드를 제공해야 합니다. 이때 메서드는 스레드로서 실행하는 하나의 작업단위, 즉. 명령의 집합이라고 볼 수 있습니다.

 

스레드가 생성되 Start() 메서드가 호출되면 이제 하나의 프로세스는 2개의 스레드가 생성된 것이며 CPU에 의해 각 스레드는 별도의 작업으로서 실행될 것입니다.

 

여기서 스레드가 왜 필요한지는 스레드의 작업단위인 메서드를 보면 알 수 있습니다. 현재 메서드의 명령을 그대로 실행하면서 동시에 다른 작업을 해야하는 경우가 발생하는 것입니다. 예를 들어

 

static void Main(string[] args)
{
    while (true) {
        string s = Console.ReadLine();

        if (s.Trim() == "exit")
            return;

        Console.WriteLine(s);
    }
}

 

위와 같은 프로그램의 경우 사용자로부터 값을 입력받아 입력받은 값을 그대로 뿌려주도록 되어 있습니다. 프로그램을 종료하려면 'exit'를 입력하면 됩니다. 그런데 좀 억지스럽지만 이 프로그램에서 3초씩마다 뭔가를 계산하고 출력하는 기능을 추가해야 한다고 가정해 보겠습니다. 그러면서 본래 프로그램이 수행하는 작업은 계속되어야 합니다.

 

static void Main(string[] args)
{
    myThread();

    while (true) {
        string s = Console.ReadLine();

        if (s.Trim() == "exit")
            return;

        Console.WriteLine(s);
    }
}

static void myThread()
{
    while (true) {
        Thread.Sleep(3000);
        Console.WriteLine("처리됨");
    }
}

 

위 예제는 스레드를 사용하지 않고 만든 경우인데 이렇게 해서는 제대로 프로그램을 사용할 수 없게 됩니다. 주 스레드는 첫명령인 myThread() 메서드를 호출하는데 이 메서드는 무한대로 3초마다 무엇인가를 처리하고 결과를 뿌려주기 때문입니다. 주 스레드가 이 작업에 매달리게 되고 결국 주 스레드는 하위의 while문을 실행할 여지가 없어지게 됩니다.

 

static void Main(string[] args)
{
    Thread t = new Thread(myThread);
    t.Start();

    while (true) {
        string s = Console.ReadLine();

        if (s.Trim() == "exit")
            return;

            Console.WriteLine(s);

    }
}

 

바로 이럴때 스레드가 필요합니다. 주 스레드는 myThread() 메서드 실행을 위한 별도의 스레드를 생성한뒤 자신이 처리해야할 부분을 계속 처리할 수 있게 됩니다.

 

일단 스레드가 생성되 실행되면 해당 스레드를 생성한 프로세스는 모든 스레드가 종료되어야만 종료될 수 있습니다. 이런 형태의 스레드를 전경 스레드(foreground thread)라 하는데 바꾸어 말하면 프로세스가 실행을 종료하기 위해서는 모든 전경 스레드가 종료되어야 하는 것입니다.

 

static void Main(string[] args)
{
    Thread t = new Thread(myThread);
    t.IsBackground = true;
    t.Start();
           

    Console.Read();
}

 

하지만 스레드의 IsBackground속성을 true로 설정하면 해당 스레드를 배경 스레드(background thread)로서 실행할 수 있게 됩니다. 배경 스레드는 전경 스레드와는 달리 해당 스레드의 종료여부와 상관없이 프로세스가 종료되면 같이 종료됩니다. 결국 프로세스가 종료되기 위한 스레드는 전경 스레드에 한정됩니다.

 

하지만 배경 스레드라 하더라도 다음과 같은 방법으로 스레드종료를 대기할 수 있습니다.

 

static void Main(string[] args)
{
    Thread t = new Thread(myThread);
    t.IsBackground = true;
    t.Start();

    t.Join();

    Console.Read();
}

 

스레드 처리중 join() 메서드를 만나면 t에 해당하는 스레드가 종료될때까지 t스레드를 호출한 주 스레드는 무한정 대기하게 됩니다.

 

스레드를 통해 메서드를 호출할때 필요하다면 특정 값을 메서드에 전달할 수도 있습니다.

 

static void Main(string[] args)
{
    Thread t = new Thread(myThread);
    t.Start(100);

    Console.Read();
}

static void myThread(object o)
{
    Console.WriteLine("입력값 : " + o.ToString());
}

 

전달가능한 매개변수는 object형이어야 하며 단 하나의 매개변수만 가능합니다. 여러개의 매개변수를 전달해야 한다면 배열을 사용하거나 사용자 정의 타입을 구현해 필요한 데이터를 전달하면 됩니다.

 

static void Main(string[] args)
{
    myValue mv = new myValue();
    mv.param1 = 100;
    mv.param2 = 200;

    Thread t = new Thread(myThread);
    t.Start(mv);

    Console.Read();
}

static void myThread(object o)
{
    myValue mv = (myValue)o;
    Console.WriteLine("입력값 : " + mv.param2);
}

 

0 0
1
블로그 이미지

클리엘