Как реализовать таймаут ожидания восстановления связи сети Интернет при загрузке файла в WinForms?

Я разрабатываю приложение на WinForms, где реализована загрузка файла с сервера. В случае потери подключения требуется выполнить следующее:

  • Отобразить текст о потере связи (это реализовано);
  • Ждать восстановления соединения сети Интернет в течение 1 минуты;
  • Если связь не восстановлена в течение минуты, отобразить сообщение "Связь с сервером потеряна" и закрыть форму загрузки.

Сейчас я использую WebClient для загрузки и BackgroundWorker для проверки соединения. Однако у меня возникают сложности с добавлением таймаута и корректной обработкой условий, когда в течении минуты появляется связь с сетью Интернет и нужно продолжить загрузку файла.

Вопросы:

  1. Как лучше реализовать таймаут ожидания на восстановление связи (1 минута)?
  2. Корректно ли я использую BackgroundWorker для проверки соединения, или лучше использовать другой подход?
  3. Как эффективно остановить загрузку и закрыть форму по истечении таймаута?

Буду благодарен за примеры и советы по улучшению текущего кода.

Пример моего кода (основные части):

private void StartDownload(String path = "")
{
    if (String.IsNullOrEmpty(path))
    {
        var dlg = new FolderPicker();
        if (dlg.ShowDialog(Handle) != true)
        {
            Close();
            return;
        }
        _lastSelectedPath = dlg.ResultPath;
    }
    else _lastSelectedPath = path;

    if (!String.IsNullOrEmpty(_lastSelectedPath) && !CanWriteToFolder(_lastSelectedPath))
    {
        MessageBox.Show(Properties.Resources.AccessViolation);
        Close();
        return;
    }

    FilePath = $@"{_lastSelectedPath}\{_fileName}";
    _downloadCompleted = false;

    _client = new WebClient();
    _client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressChanged);
    _client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted);

    try
    {
       _client.DownloadFileAsync(new Uri($"http:.../{_fileName}"), FilePath);
    }
    catch (WebException) { }

    _bw = new BackgroundWorker();
    _bw.WorkerReportsProgress = false;
    _bw.WorkerSupportsCancellation = true;
    _bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
    _bw.DoWork += Bw_DoWork;
    _bw.RunWorkerAsync();
}

private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
    _flag = false;
    _checkCount = 0;
    while (!_flag)
    {
        CheckInternet();
        Thread.Sleep(3000);
    }
    e.Cancel = _flag;
}

private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (_downloadCompleted) return;
    _downloadCompleted = true;
    _client.CancelAsync();
    Close();
}

private void CheckInternet()
{
    if (Ping()) return;
    _checkCount++;
    _flag = _checkCount >= 5;
}

private Boolean Ping()
{
    try
    {
        using (var myPing = new Ping())
        {
            var host = "8.8.8.8";
            var buffer = new byte[32];
            int timeout = 1000;
            var pingOptions = new PingOptions();
            var reply = myPing.Send(host, timeout, buffer, pingOptions);
            return reply.Status == IPStatus.Success;
        }
    }
    catch (Exception) { return false; }
}

void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        lbProgress.Text = "Cancelled";
        DialogResult = DialogResult.Cancel;
        _downloadCompleted = true;
        _bw.CancelAsync();
        _client.CancelAsync();
        Close();
    }
    else if (e.Error != null)
    {
        lbProgress.Text = Properties.Resources.ConnectWithServerLost;
        if (Ping())
        {
            _bw.CancelAsync();
            _client.CancelAsync();
            StartDownload(_lastSelectedPath);
        }
    }
    else
    {
        lbProgress.Text = "Completed";
        DialogResult = DialogResult.OK;
        _downloadCompleted = true;
        _bw.CancelAsync();
        Close();
    }
}

Ответы (0 шт):