Task<TResult> 클래스, Parallel 클래스를 이용한 병렬처리

서병수·2023년 7월 14일
0

쓰레드와 테스크

목록 보기
3/5

23년 7월 14일
코드의 병렬처리, 비동기처리를 도와주는 Task클래스이다. Tresult는 반환하는 값의 타입이다.
아래의 코드를 보면서 공부해보자.

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

namespace taskResult1
{
    internal class Program
    {
        static bool IsPrime(long number)
        {
            if (number<2)
                return false;
            if(number %2==0 && number !=2)
                return false;   
            for(long i=2; i < number; i++)
            {
                if(number %i==0)
                    return false;
            }
            
            return true;                   
        }
        static void Main(string[] args)
        {
            long from = 0;
            long to = 10000;
            int taskCount = 3;

            Func<object, List<long>> FindPrimeFunc =
                (objrange) =>
                {
                    long[] range = (long[])objrange;
                    List<long> found = new List<long>();

                    for (long i = range[0]; i < range[1]; i++)
                    {
                        if (IsPrime(i))
                            found.Add(i);
                    }
                    return found;
                };

            Task<List<long>>[] tasks = new Task<List<long>>[taskCount];
            long currentFrom = from;
            long currentTo = to/tasks.Length;    
            for(int i = 0;i<tasks.Length;i++)
            {
                Console.WriteLine("Task[{0}] : {1}~{2}", i, currentFrom, currentTo);
                tasks[i] = new Task<List<long>>(FindPrimeFunc,new long[]{currentFrom,currentTo});
                currentFrom = currentTo + 1;

                if (i == tasks.Length - 2)
                    currentTo = to;
                else
                    currentTo = currentTo + (to/tasks.Length);
            }
            Console.WriteLine("Please press enter to start...");
            Console.ReadLine();
            Console.WriteLine("Started....");

            DateTime startTime = DateTime.Now;
            List<long> total = new List<long>();
            foreach (Task<List<long>> task in tasks)
                task.Start();
            foreach (Task<List<long>> task in tasks)
            {
                task.Wait();
                total.AddRange(task.Result.ToArray());
            }
            DateTime endTime = DateTime.Now;
            TimeSpan elapsed = endTime - startTime;

            Console.WriteLine("Prime number count between {0} and {1} : {2}", from, to, total.Count);
            Console.WriteLine("Elapsed time : {0}", elapsed);
        }
    }
}
  1. IsPrime : 소수인지 아닌지 판단해주는 메서드

  2. FindPrimFunc : object를 입력으로 받아 List<Long>을 반환함.

  3. 코드 요약 : Task에 일을 나누어 주고 비동기적으로 소수를 찾는 일을 수행한다. 마지막에 결과를 합쳐주고 결린 시간을 체크한다.

    위의 코드는 사용하기가 복잡하다. 할 때마다 우리가 직접 작업을 나누어 주어야하고 결과도 합쳐주어야 하고..
    하지만 닷넷은 더 쉬운 클래스를 제공한다. 바로 Prarallel 클래스.
    이 클래스는 내부적으로 최적화하여 결과를 반환해 준다. 위의 코드를 이용하여 Parallel 클래스를 이용해보자.

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

namespace taskResult1
{
    internal class Program
    {
        static bool IsPrime(long number)
        {
            if (number<2)
                return false;
            if(number %2==0 && number !=2)
                return false;   
            for(long i=2; i < number; i++)
            {
                if(number %i==0)
                    return false;
            }
            
            return true;                   
        }
        static void Main(string[] args)
        {
            long from = 0;
            long to = 10000;
            int taskCount = 3;

            Console.WriteLine("Please press enter to start...");
            Console.ReadLine();
            Console.WriteLine("Started....");

            DateTime startTime = DateTime.Now;
            List<long> total = new List<long>();

            Parallel.For(from, to, (long i) =>
            {
                if (IsPrime(i))
                    lock (total)
                        total.Add(i);
            });
            DateTime endTime = DateTime.Now;
            TimeSpan elapsed = endTime - startTime;

            Console.WriteLine("Prime number count between {0} and {1} : {2}", from, to, total.Count);
            Console.WriteLine("Elapsed time : {0}", elapsed);
        }
    }
}

lock(total)을 걸어준 이유는 total.Add(i)를 하다가 다른 스레드랑 겹칠까봐 걸어준 것이다.
오늘은 이것으로 맞치겠다.

profile
안녕하십니까 인사올립니다

0개의 댓글