[C#] WebClient.DownlaodFileAsync를 동기로 실행시키는 방법

  복수의 WebClient 객체에서 순서대로 다운로드해야만 하는 상황이 생겨서 찾던 중 이 블로그에서 방법을 알게 돼 공유합니다.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;

namespace HsUpdaterWithSetup
{
    class Program
    {
        private static readonly object _downloadLocker = new object();

        static void Main(string[] args)
        {
            var projectName = "ABC";

            Console.WriteLine("파일 목록 불러오는 중...");

            var url = $"http://abc.def.com/path/{Uri.EscapeDataString(projectName)}/Release";

            var req = WebRequest.CreateHttp(url);

            var fileList = new List<string>();

            using (var res = req.GetResponse())
            {
                using (var stream = res.GetResponseStream())
                {
                    using (var sr = new StreamReader(stream))
                    {
                        var body = sr.ReadToEnd();

                        var matches = Regex.Matches(body, @"<a href=""(.+\.(?:exe|msi))"">");
                        
                        foreach (Match match in matches)
                        {
                            fileList.Add(match.Groups[1].Value);

                            Console.WriteLine($"파일 {match.Groups[1].Value} 확인"); 
                        }
                    }
                }
            }

            var urlList  = fileList.Select(f => $"http://abc.def.com/path/{Uri.EscapeDataString(projectName)}/Release/{f}");

            Console.WriteLine("파일 다운로드 시작");

            foreach (var d in urlList)
            {
                var wc = new WebClient();

                wc.DownloadProgressChanged += (sender, eventArgs) =>
                    Console.WriteLine($"{eventArgs.UserState}: {eventArgs.ProgressPercentage}%");

                wc.DownloadFileCompleted += (sender, eventArgs) =>
                {
                    lock (_downloadLocker)
                    {
                        Monitor.Pulse(_downloadLocker);
                    }
                };

                lock (_downloadLocker)
                {
                    wc.DownloadFileAsync(new Uri(d), Path.Combine(Environment.CurrentDirectory, Path.GetFileName(d)),
                        Path.GetFileName(d));

                    Monitor.Wait(_downloadLocker);
                }
            }
        }
    }
}

  동일한 락을 사용해 동기화시키는 방법이 있었네요. 신기합니다.

댓글

이 블로그의 인기 게시물

C# 남아도는 메모리에도 불구하고 OutOfMemoryException이 발생한다면?

USB를 뒤는 괜찮은데 앞에 꽂으면 인식이 힘들다?

MySQL 데이터 타입과 Java 데이터 타입 비교/매칭