아래 샘플 코드는 msdn에서 참고한 코드 입니다.
(
https://docs.microsoft.com/ko-kr/dotnet/standard/parallel-programming/how-to-use-parallel-invoke-to-execute-parallel-operations)
샘플 코드를 먼저 보여드린 후 결과를 토대로 설명 하겠습니다.
샘플 코드의 시나리오
- 웹 사이트에서 .txt 파일을 다운로드
- 다운로드 한 .txt 파일의 문자열을 분할
- 분할 된 문자열 배열에서 병렬로 실행할 작업 등록(GetCountForWord, GetMostCommonWords, GetLongesWord)
- 별렬 작업 실행
1: private static void GetCountForWord(string[] words, string term)
2: private static void GetMostCommonWords(string[] words)
3: private static string GetLongesWord(string[] words)
- Parallel.Invoke() 를 이용한 병렬 작업을 생성
1: // 소스 배열에서 세가지 작업을 실행
2: Parallel.Invoke(() =>
3: {
4: Console.WriteLine("Begin first task...");
5: GetLongesWord(words);
6: },
7: () =>
8: {
9: Console.WriteLine("Begin second task...");
10: GetMostCommonWords(words);
11: },
12: () =>
13: {
14: Console.WriteLine("Begin third task...");
15: GetCountForWord(words, "sleep");
16: }
17: ); //close parallel.invoke
등록된 메서들이 모두 실행된 결과 입니다. 실행된 메서드들은 쓰레드 풀에서 각각 실행되기에 순서가 보장되지 않아 first, second, third가 순서대로 출력되었지만 다시 실행하면 또 다른 순서대로 출력 됩니다. Task2, Task1, Task3 순서로 출력되는 걸 보면 아시겠죠?^^
- 정리
- 암시적으로 Task를 생성하여 실행 할 때는 Parallel.Invoke()를 사용
- 등록된 작업은 쓰레드 풀에서 실행
- 순서 보장을 할 수 없음
# 전체 소스
1: /// <summary>
2: /// 암시적으로 작업 만들기 및 실행
3: /// Parallel.Invoke를 사용하여 병렬 작업 실행
4: /// </summary>
5: class Program
6: {
7: static void Main(string[] args)
8: {
9: string[] words = CreateWordArray(@"http://www.gutenberg.org/files/54700/54700-0.txt");
10: #region 병렬 작업 만들기 및 실행
11: // 소스 배열에서 세가지 작업을 실행
12: Parallel.Invoke(() =>
13: {
14: Console.WriteLine("Begin first task...");
15: GetLongesWord(words);
16: },
17: () =>
18: {
19: Console.WriteLine("Begin second task...");
20: GetMostCommonWords(words);
21: },
22: () =>
23: {
24: Console.WriteLine("Begin third task...");
25: GetCountForWord(words, "sleep");
26: }
27: ); //close parallel.invoke
28: Console.WriteLine("Returned from Parallel.Invoke");
29: #endregion
30: Console.WriteLine("Press any key to exit");
31: Console.ReadKey();
32: }
33: #region HelperMethods
34: /// <summary>
35: /// 단어 배열에서 지정된 단어를 찾는다.
36: /// </summary>
37: /// <param name="words"></param>
38: /// <param name="term"></param>
39: private static void GetCountForWord(string[] words, string term)
40: {
41: var findWord = from word in words
42: where word.ToUpper().Contains(term.ToUpper())
43: select word;
44: Console.WriteLine($@"Task 3 -- The word ""{term}"" occurs {findWord.Count()} times.");
45: }
46: /// <summary>
47: /// 단어의 길이가 6 초과되는 단어를 그룹화 하여 그룹 개수를 내림차순으로 정렬한 결과를 10개를 조회 한다.
48: /// </summary>
49: /// <param name="words"></param>
50: private static void GetMostCommonWords(string[] words)
51: {
52: var frequencyOrder = from word in words
53: where word.Length > 6
54: group word by word into g
55: orderby g.Count() descending
56: select g.Key;
57: var commonWords = frequencyOrder.Take(10);
58: StringBuilder sb = new StringBuilder();
59: sb.AppendLine("Task 2 -- The most common words are:");
60: foreach (var v in commonWords)
61: {
62: sb.AppendLine(" " + v);
63: }
64: Console.WriteLine(sb.ToString());
65: }
66: /// <summary>
67: /// 가장 긴 길이의 단어를 가져옵니다.
68: /// </summary>
69: /// <param name="words"></param>
70: /// <returns></returns>
71: private static string GetLongesWord(string[] words)
72: {
73: var longestWord = (from w in words
74: orderby w.Length descending
75: select w).First();
76: Console.WriteLine($"Task 1 -- The longest word is {longestWord}.");
77: return longestWord;
78: }
79: /// <summary>
80: /// 동기적으로 웹 페이지의 문자열을 다운로드 합니다.
81: /// </summary>
82: /// <param name="uri"></param>
83: /// <returns></returns>
84: static string[] CreateWordArray(string uri)
85: {
86: Console.WriteLine($"Retrieving from {uri}");
87: // 웹 페이지 문자열을 다운로드
88: string s = new WebClient().DownloadString(uri);
89: // 문자열을 단어 배열로 분리
90: return s.Split(
91: new char[] { ' ', '\u000A', ',', '.', ';', ':', '-', '_', '/' },
92: StringSplitOptions.RemoveEmptyEntries);
93: }
94: #endregion
95: }
댓글
댓글 쓰기