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);
}
}
}
IsPrime : 소수인지 아닌지 판단해주는 메서드
FindPrimFunc : object를 입력으로 받아 List<Long>
을 반환함.
코드 요약 : 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)를 하다가 다른 스레드랑 겹칠까봐 걸어준 것이다.
오늘은 이것으로 맞치겠다.