[c#] task와 lambda expression을 이용한 멀티 뜨레드

전에는 멀티 뜨레드를 이용할 때 thread나 ThreadPool을 이용했지만 요샌 task를 쓴다. task로 새 뜨레드를 만들 땐 run이나 StartNew를 이용한다. 전자가 더 편하고 빠르다.

run을 이용하면 새로운 뜨레드로 실행할 메떠드를 그대로 쓸 수 있다. 하지만 람다식을 써야 한다. StartNew로 하려면 대상 메떠드가 패러미터로 object만 받을 수 있다. 이걸 다시 타입캐스트해서 써야 하므로 번거롭다.

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() => Method1(1));
}

void Method1(int int1)
{
    //
}

private void button2_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(Method2, 1);
}

void Method2(object object1)
{
    int int1 = (int)object1;

    //
}

지나치게 간결한 건 직관적이지 않고 다양하게 해석할 여지가 커서 어렵다. 그 대표적인 예가 람다식이다. 람다식은 간결하지만 어렵다. 왠만해서는 쓰고 싶지 않지만 현대 컴퓨터 프로그래밍에서는 꼭 넘어야 할 벽이다.

람다식은 수학의 lambda calculus에서 응용된 거다. 람다 계산법은 함수에서 등호를 없애 그 자체를 변수처럼 쓸 수 있게 한다. 어려운 말로는 익명 함수라고도 한다. 람다 계산법에서는 앞에 변수가 오고 뒤에 식이 붙으며 이들 사이를 .가 연결한다. 람다식에서는 =>가 .를 대신한다.

위 코드에서 ()는 아규먼트이고 Method(1)이 식이다. ()는 아규먼트가 없다는 뜻이다. Method1은 1이라는 아규먼트를 받지만 Method1(1)은 아규먼트가 필요하지 않은 그 자체로 식이다. 복잡하게 여겨지지만 아래와 같이 풀어서 쓰면 쉽게 이해할 수 있다.

private void button3_Click(object sender, EventArgs e)
{
    Task.Run(RunMethod1);
}

void RunMethod1()
{
    Method1(1);
}

람다식을 쓰면 위 코드에서 RunMethod1()가 이름 없이 표현되므로 익명 함수라 하는 거다.

Method1은 반환하는 게 없다. 이렇게 받는 것도 없고 반환하지도 않으며 그저 무언가만 하는 걸 action이라 한다. run은 여러 형태의 패러미터들을 갖는데 action도 그 가운데 하나다.