проблема: у нас есть некоторый IP-адрес, тогда мы должны выполнить ping каждого из них по времени, указанному пользователем, например, ping 192.168.0.1 каждые 400 мс, ping 192.168.137.20 каждые 40000 мс и т. д. ... как мы можем обрабатывать подобные ситуации асинхронным образом?обрабатывать большое количество асинхронных заданий
это где я нагрузить целевые показатели информации из базы данных и создать датчик для каждого из них:
public class PingService
{
private CancellationTokenSource _cancel;
private List<PingSensor> _pings;
private IRepository<IPDevice> _deviceRepository;
public PingService()
{
_cancel = new CancellationTokenSource();
_pings = new List<PingSensor>();
_deviceRepository = ObjectFactory.GetInstance<IRepository<IPDevice>>();
}
public void Start()
{
Action act = new Action(() =>
{
IQueryable<IPDevice> allDevices = _deviceRepository.GetAll();
foreach (IPDevice device in allDevices)
{
PingResultCollector collector = new PingResultCollector(device);
_pings.Add(new PingSensor(device.Address, collector, device.CheckDuration, _cancel.Token));
}
foreach (PingSensor _ping in _pings)
{
_ping.DoDiscovery();
}
});
Task.Factory.StartNew(act);
}
public void Stop()
{
_cancel.Cancel();
}
}
и это, где мы делаем пинг и ждать задержек, указанных пользователем, собирает отклик и .. .
public class PingSensor
{
private string _address;
Ping _ping;
private bool lastRequestReplayed;
private int _delay;
private CancellationToken _cancellationToken;
private PingResultCollector _resultCollector;
public PingSensor(string address, PingResultCollector resultCollector, int delay, CancellationToken CancellationToken)
{
_address = address;
_cancellationToken = CancellationToken;
_ping = new Ping();
_resultCollector = resultCollector;
_ping.PingCompleted += _ping_PingCompleted;
_delay = delay;
}
void _ping_PingCompleted(object sender, PingCompletedEventArgs e)
{
if (_cancellationToken.IsCancellationRequested)
return;
lastRequestReplayed = true;
//_eventHandler(sender, e);
if (_resultCollector != null)
_resultCollector.CollectData(new PingStatus()
{
PingStatusId = Guid.NewGuid(),
Address = e.Reply == null ? "" : e.Reply.Address.ToString(),
Status = e.Reply == null ? e.Error.Message : e.Reply.Status.ToString(),
Target = e.UserState.ToString(),
ResponseTime = e.Reply == null ? 0 : e.Reply.RoundtripTime,
UpdateTime = DateTime.UtcNow
});
}
public void DoDiscovery()
{
lastRequestReplayed = true;
Action act = new Action(() =>
{
while (_cancellationToken.IsCancellationRequested!=true)
{
if (_cancellationToken.IsCancellationRequested)
return;
byte[] data = new byte[2];
if (lastRequestReplayed)
{
_ping.SendAsync(_address, 30000, data, _address);
lastRequestReplayed = false;
}
if (_cancellationToken.IsCancellationRequested)
return;
Thread.Sleep(_delay);
if (_cancellationToken.IsCancellationRequested)
return;
}
});
Task.Factory.StartNew(act);
}
}
и проблема с этим кодом является его создать один поток для каждого датчика, что это значит, если я имел 500 цель для пинг у меня также есть 500 нитей! любое предложение? и поэтому извините за мой плохой английский: D
Важно отметить, что это _will not_ start 500 threads. Это будет ** queue ** 500 задач, среда выполнения решит, сколько потоков будет выполнено для выполнения на основе среды, в которой работает код, но поток 'Task'! =. Поэтому, если вам действительно нужны эти 500 задач, чтобы определенно работать параллельно, то это, вероятно, не очень хорошее решение для вас. – CodingGorilla
thx для вашего комментария, я понимаю это, и я не тестировал его на самом деле с 500 задачами, но для 70 целей я получаю 70 потоков, и это точно моя проблема, некоторые задачи наклонены на долгое время, и это может занять 30 секунд одна задача снова работать – cyberw0lf
У вас есть возможность использовать .Net 4.5? –