Я пытаюсь написать класс, который непрерывно пингует «в фоновом режиме» список одного или нескольких устройств и сообщает о результатах объекту Progress в главном классе GUI. Я очень новичок в async / await и Tasks, но мой код, кажется, отлично работает на моем p c, даже если я знаю, что он не очень хорошо разработан. Но когда я запускаю приложение на другом компьютере, оно генерирует исключение InvalidOperationException из объекта Progress, так как словарь изменяется. Я думаю, что это происходит, когда я назначаю новый PingService той же переменной. Класс PingService начинает пинговать (SendPingAsyn c) список IP-адресов для функции с инф. l oop, который обновляет объект PingServiceReply для каждой итерации списка и затем «сообщает» его объекту Progress.
Как это можно сделать, и что я делаю неправильно?
Вот код.
Класс PingSeviceReply
public class PingServiceReply
{
private Dictionary<string, bool> ipDictionary;
internal PingServiceReply()
{
ipDictionary = new Dictionary<string, bool>();
}
public void SetIpStatus(string ip, bool status)
{
if (ipDictionary.ContainsKey(ip))
{
ipDictionary[ip] = status;
}
else
{
ipDictionary.Add(ip, status);
}
}
public Dictionary<string, bool> GetStatusDictionary()
{
return ipDictionary;
}
public bool AreAllOnline()
{
foreach (bool value in ipDictionary.Values)
{
if (!value)
{
return false;
}
}
return true;
}
}
Класс PingService
public class PingService
{
private string name;
private List<string> ipList;
private IProgress<PingServiceReply> progress;
private CancellationTokenSource cts;
private int timeout;
private Task tsk;
public PingService(string name, List<string> ipList, int timeoutInMillliseconds, IProgress<PingServiceReply> progress)
{
this.name = name;
this.ipList = ipList;
this.progress = progress;
this.timeout = timeoutInMillliseconds;
}
public PingService(string name, string ip, int timeoutInMillliseconds, IProgress<PingServiceReply> progress)
{
this.name = name;
this.ipList = new List<string>();
ipList.Add(ip);
this.progress = progress;
this.timeout = timeoutInMillliseconds;
}
public PingService()
{
cts = new CancellationTokenSource();
}
private async Task ContinuousPingAsync()
{
var ping = new System.Net.NetworkInformation.Ping();
PingReply singleResponse;
PingServiceReply ruleResponse = new PingServiceReply();
while (!cts.Token.IsCancellationRequested)
{
foreach (string ip in ipList)
{
singleResponse = await ping.SendPingAsync(ip, timeout).ConfigureAwait(false);
ruleResponse.SetIpStatus(ip, singleResponse.Status == IPStatus.Success);
}
progress.Report(ruleResponse);
}
}
public void StartService()
{
cts = new CancellationTokenSource();
tsk = ContinuousPingAsync();
}
public void StopService()
{
cts.Cancel();
}
public string GetName()
{
return name;
}
}
Объект прогресса
IProgress<PingServiceReply> pingProgress = new Progress<PingServiceReply>(HandleSinglePing);
private void HandleSinglePing(PingServiceReply report)
{
if (report.AreAllOnline())
{
//online
}
else
{
//offline
}
}
Как использовать все в классе gui, в поле со списком событие selectedItemChanged
comboService.StopService();
comboService = new PingService("Combo", (string) comboBox.SelectedItem, 1000, pingProgress);
comboService.StartService();