- Parallel.ForEach()의 활용
Parallel.ForEach() 메서드는 제네릭 컬렉션을 순회하는 데 사용됩니다. ASP.NET Core 웹 애플리케이션 프로젝트에서 이를 사용해 보겠습니다.
먼저, Member.cs라는 클래스를 생성하고 다음과 같이 코드를 작성합니다:
public class Member
{
public int Id { get; set; }
public string Name { get; set; }
}
그 다음, Index.cshtml.cs 파일의 IndexModel 클래스에 테스트 메서드 ParallelForEachDemo()를 추가합니다:
public void OnGet()
{
ParallelForEachDemo();
}
public string ResultDisplay; // 페이지에서 값을 가져올 변수
public void ParallelForEachDemo()
{
List<Member> memberList = new List<Member>
{
new Member{ Id=1, Name="김철수" },
new Member{ Id=2, Name="박영희" },
new Member{ Id=3, Name="이길동" },
new Member{ Id=4, Name="최정민" },
new Member{ Id=5, Name="홍길자" }
};
string allNames1 = string.Empty;
Stopwatch timer1 = new Stopwatch();
timer1.Start();
foreach (Member member in memberList)
{
allNames1 += member.Name + ",";
Thread.Sleep(10); // 시간 소요 작업을 시뮬레이션
}
timer1.Stop();
string allNames2 = string.Empty;
Stopwatch timer2 = new Stopwatch();
timer2.Start();
Parallel.ForEach(memberList, member => // 멀티스레드 순회
{
allNames2 += member.Name + ",";
Thread.Sleep(10); // 시간 소요 작업을 시뮬레이션
});
timer2.Stop();
ResultDisplay = string.Format("단일 스레드 순회 시간: {0}ms, 멀티스레드 순회 시간: {1}ms",
timer1.ElapsedMilliseconds, timer2.ElapsedMilliseconds);
}
Index.cshtml.cs 파일에서 ResultDisplay 변수의 값을 출력하는 부분은 다음과 같습니다:
<div class="text-center">
<h1 class="display-4">환영합니다</h1>
<br />
<p>@Model.ResultDisplay</p>
</div>
컴파일 후 실행하면, 결과는 단일 스레드보다 멀티스레드가 더 빠르게 처리됨을 확인할 수 있습니다.
- Parallel.Invoke()의 활용
다음으로, 여러 웹사이트에 동시에 접속하여 응답 문자열 길이를 측정하는 예제를 살펴보겠습니다. 이 역시 Index.cshtml.cs 파일의 IndexModel 클래스 내에서 구현합니다:
public void CountLength(string source, string url)
{
long length = 0;
HttpWebRequest request = WebRequest.CreateHttp(url); // 주어진 URL로 요청 생성
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); // 응답 객체 획득
length = response.ContentLength; // 응답 내용 길이 획득
DisplayResult += "<tr><td>" + source + "</td><td>" + Thread.CurrentThread.ManagedThreadId + "</td>" +
"<td>" + url + "</td><td>" + length + "</td></tr>";
}
단일 스레드로 세 번의 함수 호출을 순차적으로 실행하는 코드는 다음과 같습니다:
public string SingleFetch()
{
Stopwatch watch1 = new Stopwatch();
watch1.Start();
CountLength("single", "http://www.google.com");
CountLength("single", "http://www.naver.com");
CountLength("single", "http://www.daum.net");
watch1.Stop();
return watch1.ElapsedMilliseconds.ToString();
}
멀티스레드로 세 번의 함수 호출을 병렬로 실행하는 코드는 다음과 같습니다:
public string MultiFetch()
{
Stopwatch watch2 = new Stopwatch();
watch2.Start();
Parallel.Invoke(
() => CountLength("multi", "http://www.google.com"),
() => CountLength("multi", "http://www.naver.com"),
() => CountLength("multi", "http://www.daum.net")
);
watch2.Stop();
return watch2.ElapsedMilliseconds.ToString();
}
OnGet() 메서드에서는 각각 단일 스레드와 멀티스레드 방법을 호출하며 결과를 표시하기 위한 코드도 포함되어 있습니다:
public string ResultDisplay;
public string DisplayResult;
public void OnGet()
{
string timeSingle = SingleFetch(); // 단일 스레드 실행 시간
string timeMulti = MultiFetch(); // 멀티스레드 실행 시간
ResultDisplay = string.Format("단일 스레드 시간: {0}ms, 멀티스레드 시간: {1}ms", timeSingle, timeMulti);
DisplayResult = "| 타입 | 스레드 ID | 웹사이트 | 응답 길이 |
|---|---|---|---|";
}
마지막으로, Index.cshtml 파일에서 결과를 표시하는 코드는 다음과 같습니다:
<div class="text-center">
<h1 class="display-4">환영합니다</h1>
<br />
<p>@Model.ResultDisplay</p>
<br />
<p>@Html.Raw(Model.DisplayResult)</p>
</div>
이 코드를 컴파일하고 실행하면, 멀티스레드 방식이 단일 스레드 방식보다 빠른 것을 확인할 수 있습니다.