Асинхронные сайт монитор


У меня есть класс, который отвечает за проверку того, сайт вверх или вниз. Я сделал это, чтобы работать асинхронно, но хотелось бы критики, если это хорошо/плохо или если есть еще лучше способ сделать это.

class UrlChecker {
    private readonly IValidationCondition _condition;
    private readonly Dictionary<string, UrlStatus> _status = new Dictionary<string, UrlStatus>();
    private readonly object _lock = new object();

    public UrlChecker(IValidationCondition condition) {
        _condition = condition;
    }

    public void CheckRange(IEnumerable<string> urls, Action<Dictionary<string, UrlStatus>> callback) {
        var options = new ParallelOptions {MaxDegreeOfParallelism = 5};
        Parallel.ForEach(urls, options, Check);

        callback(_status);
    }

    private void Check(string url) {
        Console.WriteLine("Checking " + url);

        var req = (HttpWebRequest) WebRequest.Create(url);
        req.Timeout = 10 * 10000; // 10 seconds

        HttpWebResponse resp;

        try {
            resp = (HttpWebResponse)req.GetResponse();    
        }
        catch(WebException ex) {
            // We got an exception, consider it as down
            lock (_lock)
                _status.Add(url, UrlStatus.Down);
            return;
        }

        if(resp.StatusCode != HttpStatusCode.OK) {
            lock (_lock)
                _status.Add(url, UrlStatus.Down);
            return;
        }

        using(var reader = new StreamReader(resp.GetResponseStream())) {
            // Check for empty response
            var html = reader.ReadToEnd();
            if(string.IsNullOrEmpty(html)) {
                lock(_lock) {
                    _status.Add(url, UrlStatus.Down);
                }
            }

            // Validate against condition
            if(!_condition.IsValid(html)) {
                lock(_lock) {
                    _status.Add(url, UrlStatus.Down);
                }
                return;
            }
        }

        // We reached the end without problems, it's a valid url
        lock(_lock) {
            _status.Add(url, UrlStatus.OK);
        }
    }
}

Это называется вот так:

checker.CheckRange(urls, status => {
    if(status.Any(x => x.Value == UrlStatus.Down))
        EmailFailing(message);
});

Второй параметр-это, очевидно, обратный вызов, который вызывается, когда все проверки закончены.

Я правильно замок?

Это приемлемый способ сделать это? Проверка с помощью программы Fiddler доказывает, что она работает правильно, но есть лучший способ?



2730
4
задан 15 апреля 2011 в 11:04 Источник Поделиться
Комментарии
4 ответа

Я не понимаю, как это работает асинхронно. обратного вызова(_status); будет по-прежнему быть вызван только после того, как вся обработка закончена, параллельно или нет. В этом случае делает обратный вызов излишним, так как он делает то же, что простой возвращаемое значение.

Если вы хотите, чтобы сделать его асинхронным вам необходимо хранить обратного вызова в качестве переменной-члена, но вернуться сразу в CheckRange. Начать фактическую обработку в отдельном потоке, например, с помощью BackgroundWorker. После этого, по окончании выполнения, вы можете вызывать хранимые обратного результата.

4
ответ дан 15 апреля 2011 в 01:04 Источник Поделиться

Единственная проблема, которую я вижу, если ваша реализация IValidationCondition не является потокобезопасным. Это не похоже на то, что бы любое государство, но я подумал, что он, наверное, должен быть явно указано в документации код (или как требование интерфейса или конструктор UrlChecker по).

3
ответ дан 16 апреля 2011 в 12:04 Источник Поделиться

сумма, которую вы замок не так круто..... Я бы "добавить" метод, который делает ваш замок для вас

общее правило с многопоточностью..... сделать все ваши синхронизации в наиболее минимальный минимальный кусок кода, как это возможно. т. е., попробовать и сделать все через одно место, так что у вас есть ограниченное количество точек отказа. ( лично я склонен помещать вещи через синхронизированы очереди )

3
ответ дан 17 апреля 2011 в 09:04 Источник Поделиться

Вы рассматривали с помощью ConcurrentDictionary , а не реализации запереться? Это в комплекте с реактивными расширениями , если вы еще на .Нетто 3.5.

3
ответ дан 18 апреля 2011 в 11:04 Источник Поделиться