[C# 문법] C# async, await 이용하여 비동기 예제 프로그램 만들기
- C#/C# 문법
- 2020. 12. 21. 19:25
안녕하세요.
오늘은 C# 문법에서 async, await 키워드를 이용하여 비동기 예제 프로그램을 만들어 보려고 합니다.
동기와 비동기에 대해서 아주 간단하게? 차이점을 말씀을 드리면,
동기는 한마디로 동시에 행동이 일어 난다는건데요. 쉽게 말해 요청과 결과가 한 자리에서 바로 일어나는 걸 동기라고 이해하시면 되겠습니다.
반대로 비동기는, 동시에 일어나지 않고, 요청과 결과가 따로 일어날 수 있는 경우를 뜻하는데요.
오늘은 C#에서 비동기가 일어나도록 프로그램을 아주 간단하게? 만들어 보려고 합니다.
바로, async, await 2개의 키워드를 사용하여 비동기 프로그램을 만들 수 있는데요.
먼저 아래와 같이 WPF에서 UI를 구성해 주시기 바랍니다.
[UI 구성 모습]
UI 구성 모습
UI xaml 소스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTest"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="400">
<Border Padding="10">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="비동기 프로그램 예제" FontWeight="Bold" Margin="0 10 0 0"/>
<Button x:Name="uiBtn_Async" Click="uiBtn_Async_Click" Grid.Column="1" Grid.Row="0" Margin="10 10 10 10" Content="Start" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="결과물 출력" />
<RichTextBox x:Name="uiRtb_Output" Height="500" Grid.ColumnSpan="2" Grid.Row="2" IsReadOnly="True" AcceptsReturn="True"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Grid>
</StackPanel>
</Border>
</Window>
|
cs |
UI 소스코드는 위와 같습니다.
이제 Start 버튼을 클릭하면, 서로 다른 일을 하는 2개의 비동기 메서드를 만들어서 결과물이 출력되도록 하도록 하겠습니다.
예제 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
FlowDocument flowDoc = new FlowDocument();
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 비동기 시작 버튼 클릭 이벤트
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void uiBtn_Async_Click(object sender, RoutedEventArgs e)
{
Start();
}
private async Task Start()
{
Task task1 = FirstAsync();
Task task2 = SecondAsync();
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"비동기 시작")));
uiRtb_Output.Document = flowDoc;
}));
await task1;
await task2;
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"비동기 종료")));
uiRtb_Output.Document = flowDoc;
}));
}
/// <summary>
/// 첫 번째, 비동기 메서드 선언
/// </summary>
/// <returns></returns>
private async Task FirstAsync()
{
await Task.Run( () =>
{
for(int idx = 0; idx < 5; idx++)
{
Thread.Sleep(500);
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"FirstAsync")));
uiRtb_Output.Document = flowDoc;
}));
}
});
}
/// <summary>
/// 두 번째, 비동기 메서드 선언
/// </summary>
/// <returns></returns>
private async Task SecondAsync()
{
await Task.Run( () =>
{
for(int idx = 0; idx < 5; idx++)
{
Thread.Sleep(500);
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"SecondAsync")));
uiRtb_Output.Document = flowDoc;
}));
}
});
}
}
}
|
cs |
실행 결과
위와 같이 “비동기시작” 문구가 출력이 되고, 그 다음에 비동기 메서드 1, 2 번째 메서드가 각각 5번씩 출력이 되면서 비동기 메서드가 모두 끝나서야 마지막으로 “비동기종료” 문구가 출력되는 것을 확인하실 수 있습니다.
이렇게 비동기 메서드가 끝나야 출력되는 이유는 await 키워드 때문인데요.
예제 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
FlowDocument flowDoc = new FlowDocument();
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 비동기 시작 버튼 클릭 이벤트
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void uiBtn_Async_Click(object sender, RoutedEventArgs e)
{
Start();
}
private async Task Start()
{
Task task1 = FirstAsync();
Task task2 = SecondAsync();
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"비동기 시작")));
uiRtb_Output.Document = flowDoc;
}));
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"비동기 종료")));
uiRtb_Output.Document = flowDoc;
}));
}
/// <summary>
/// 첫 번째, 비동기 메서드 선언
/// </summary>
/// <returns></returns>
private async Task FirstAsync()
{
await Task.Run( () =>
{
for(int idx = 0; idx < 5; idx++)
{
Thread.Sleep(500);
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"FirstAsync")));
uiRtb_Output.Document = flowDoc;
}));
}
});
}
/// <summary>
/// 두 번째, 비동기 메서드 선언
/// </summary>
/// <returns></returns>
private async Task SecondAsync()
{
await Task.Run( () =>
{
for(int idx = 0; idx < 5; idx++)
{
Thread.Sleep(500);
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
{
flowDoc.Blocks.Add(new Paragraph(new Run($"SecondAsync")));
uiRtb_Output.Document = flowDoc;
}));
}
});
}
}
}
|
cs |
실행 결과
만약 위와 같이 소스코드에서 await 키워드를 안쓰게 되면, “비동기시작”, “비동기종료”가 찍히면서 동시에 비동기 메서드 1,2가 각각 수행되면서 출력되는 것을 확인하실 수 있습니다.
'C# > C# 문법' 카테고리의 다른 글
[C# 문법] C# as 연산자 (0) | 2020.12.23 |
---|---|
[C# 문법] C# async 비동기 메서드 반환값 받기 (0) | 2020.12.22 |
[C# 문법] C# Null 관련 연산자(??, .? 기호) (0) | 2020.12.19 |
[C# 문법] 추상 클래스, 추상 메서드 (abstract) (0) | 2020.12.18 |
[C# 문법] C# 다형성이란 (0) | 2020.12.17 |
이 글을 공유하기