using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Study
{
[TestClass]
public class ParallelTest
{
///
/// Parallel + TaskRun
/// 가끔씩 실패함.
///
[TestMethod]
public void ParallelTaskRun()
{
var alphabetAndNumber = Prepare();
var taskResults = new List>();
Parallel.ForEach(alphabetAndNumber.Item1, alphabet =>
{
foreach(var number in alphabetAndNumber.Item2)
{
var t = Task.Run(() => DoMehtod(alphabet, number));
Assert.AreNotEqual(null, t);
taskResults.Add(t);
}
});
Task.WaitAll(taskResults.ToArray());
Console.WriteLine($"TEST End");
}
///
/// Task.Run()만 수행
///
[TestMethod]
public void TaskRun()
{
var alphabetAndNumber = Prepare();
var alphabetAndNumbers = new List();
foreach(var alphabet in alphabetAndNumber.Item1)
{
foreach(var number in alphabetAndNumber.Item2)
{
var str = $"{alphabet}.{number}".ToUpperInvariant();
alphabetAndNumbers.Add(str);
}
}
var taskResults = new List();
foreach(var item in alphabetAndNumbers)
{
var t = Task.Run(() => DoMehtod(item[0], item[0]));
taskResults.Add(t);
}
Task.WaitAll(taskResults.ToArray());
Console.WriteLine($"TEST End");
}
///
/// Parallel 를 PC의 ProcessorCount 만금 동시접속 ==> 기본적으로 Parallel의 기본값이기 때문에 의미 없음
///
[TestMethod]
public void ParallelSemaphoreSlimOnlyProcessorCount()
{
var alphabetAndNumber = Prepare();
var concurrencySemaphore = new SemaphoreSlim(Environment.ProcessorCount);
Parallel.ForEach(alphabetAndNumber.Item1, alphabet =>
{
foreach(var number in alphabetAndNumber.Item2)
{
concurrencySemaphore.Wait();
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} Enter");
DoMehtod(alphabet, number);
concurrencySemaphore.Release();
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} End");
}
});
Console.WriteLine($"TEST End");
}
// 기본 Parallel 사용
[TestMethod]
public void ParallelSingle()
{
var alphabetAndNumber = Prepare();
Parallel.ForEach(alphabetAndNumber.Item1, alphabet =>
{
foreach(var number in alphabetAndNumber.Item2)
{
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} Enter");
DoMehtod(alphabet, number);
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} End");
};
});
Console.WriteLine($"TEST End");
}
[TestMethod]
public void ParallelParallel()
{
var alphabetAndNumber = Prepare();
Parallel.ForEach(alphabetAndNumber.Item1, alphabet =>
{
Parallel.ForEach(alphabetAndNumber.Item2, number =>
{
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} Enter");
DoMehtod(alphabet, number);
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} End");
});
});
Console.WriteLine($"TEST End");
}
///
/// Parallel 을 사용하면서 SemaphoreSlim(1)을 사용하며 1개의 코어만 접근 가능하게 함.
///
[TestMethod]
public void ParallelOnlySingleThreadEnter()
{
var alphabetAndNumber = Prepare();
var concurrencySemaphore = new SemaphoreSlim(1);
Parallel.ForEach(alphabetAndNumber.Item1, alphabet =>
{
foreach(var number in alphabetAndNumber.Item2)
{
concurrencySemaphore.Wait();
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} Enter");
DoMehtod(alphabet, number);
concurrencySemaphore.Release();
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} End");
}
});
Console.WriteLine($"TEST End");
}
///
/// 단순 싱글코어 테스트
///
[TestMethod]
public void SingleCore()
{
var alphabetAndNumber = Prepare();
foreach(var alphabet in alphabetAndNumber.Item1)
{
foreach(var number in alphabetAndNumber.Item2)
{
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} Enter");
DoMehtod(alphabet, number);
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} End");
}
}
Console.WriteLine($"TEST End");
}
private Tuple Prepare()
{
// a to z
var alphabets = Enumerable.Range('a', 'z' - 'a' + 1).Select(i => (Char)i).ToArray();
// 1 to 5
var numbers = Enumerable.Range('1', '5' - '1' + 1).Select(i => (Char)i).ToArray();
return new Tuple(alphabets, numbers);
}
private string DoMehtod(char alphabet, char number)
{
var str = $"{alphabet}.{number}".ToUpperInvariant();
Thread.Sleep(100);
Console.WriteLine($"{Task.CurrentId}, {DateTime.Now} {alphabet}{number} Do");
return str;
}
}
}