Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C#] WinForm : 비동기 작업 본문

Programming/C#

[Programming/C#] WinForm : 비동기 작업

scii 2020. 10. 3. 21:40

async와 await가 C#에 도입되기 전까지는 백그라운드 작업을 수행하면서도 사용자에게 잘 응답하는 프로그램을 만들기는 쉽기만한 일은 아니었다. async와 await가 도입됨에따라 개발자가 보다 쉽게 응답성이 좋은 프로그램을 만들 수 있게 되었다.

Step 1. UI 구성를 구성한다. MainForm 위에 다음과 같이 컨트롤을 배치한다.

컨트롤이 배치된 모습

Step 2. CopySync() & CopyAsync() 메소드 구현한다. 동기 파일 복사를 하는 CopySync()와 비동기 파일 복사를 하는CopyAsync() 코드를 추가해보자.

private async Task<long> CopyAsync(string fromPath, string toPath)
{
    btnSyncCopy.Enabled = false;
    long fileSize = 0;

    using (FileStream fromStream = new FileStream(fromPath, FileMode.Open),
        toStream = new FileStream(toPath, FileMode.Create))
    {
        byte[] buffer = new byte[1024 * 1024];
        int nRead = 0;
        while ((nRead = await fromStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            await toStream.WriteAsync(buffer, 0, nRead);
            fileSize += nRead;

            // 프로그래스바에 현재 파일 복사 상태 표시
            // 현재까기 복사된 파일 크기 / 총 파일 크기 * 프로그레스바 최대값
            pbCopy.Value = (int)(((double)fileSize / (double)fromStream.Length) * pbCopy.Maximum);
        }
    }
    return fileSize;
}

private long CopySync(string fromPath, string toPath)
{
    btnAsyncCopy.Enabled = false;
    long fileSize = 0;

    using (FileStream fromStream = new FileStream(fromPath, FileMode.Open),
        toStream = new FileStream(toPath, FileMode.Create))
    {
        byte[] buffer = new byte[1024 * 1024];
        int nRead = 0;
        while ((nRead = fromStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            toStream.Write(buffer, 0, nRead);
            fileSize += nRead;

            // 프로그래스바에 현재 파일 복사 상태 표시
            // 현재까기 복사된 파일 크기 / 총 파일 크기 * 프로그레스바 최대값
            pbCopy.Value = (int)(((double)fileSize / (double)fromStream.Length) * pbCopy.Maximum);
        }
    }
    return fileSize;
}

Step 3. 각 컨트롤에 대한 이벤트 처리기를 만든다.

private async void btnAsyncCopy_Click(object sender, EventArgs e)
{
    long fileSize = await CopyAsync(txtSource.Text, txtTarget.Text);
}

private void btnSyncCopy_Click(object sender, EventArgs e)
{
    long fileSize = CopySync(txtSource.Text, txtTarget.Text);
}

private void btnCancel_Click(object sender, EventArgs e)
{
    MessageBox.Show("UI 반응 테스트!");
}

private void btnFindSource_Click(object sender, EventArgs e)
{
    OpenFileDialog dlg = new OpenFileDialog();
    if(dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        txtSource.Text = dlg.FileName;
    }
}

private void btnFindTarget_Click(object sender, EventArgs e)
{
    OpenFileDialog dlg = new OpenFileDialog();
    if(dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        txtTarget.Text = dlg.FileName;
    }
}

<Sync Copy> 버튼을 클릭하여 파일 복사를 진행할 때 <Cancel> 버튼을 눌러도 UI가 반응하지 못한다.
하지만 <Async Copy> 버튼을 클릭하여 파일 복사를 진행할 때 <Cancel> 버튼을 누르면 UI가 아주 잘 반응한다.

Comments