Как реализовать таймаут ожидания восстановления связи сети Интернет при загрузке файла в WinForms?
Я разрабатываю приложение на WinForms, где реализована загрузка файла с сервера. В случае потери подключения требуется выполнить следующее:
- Отобразить текст о потере связи (это реализовано);
- Ждать восстановления соединения сети Интернет в течение 1 минуты;
- Если связь не восстановлена в течение минуты, отобразить сообщение "Связь с сервером потеряна" и закрыть форму загрузки.
Сейчас я использую WebClient для загрузки и BackgroundWorker для проверки соединения. Однако у меня возникают сложности с добавлением таймаута и корректной обработкой условий, когда в течении минуты появляется связь с сетью Интернет и нужно продолжить загрузку файла.
Вопросы:
- Как лучше реализовать таймаут ожидания на восстановление связи (1 минута)?
- Корректно ли я использую BackgroundWorker для проверки соединения, или лучше использовать другой подход?
- Как эффективно остановить загрузку и закрыть форму по истечении таймаута?
Буду благодарен за примеры и советы по улучшению текущего кода.
Пример моего кода (основные части):
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();
}
}