C# 正在检查IIS Express上多个页面的HTTP状态:使IIS Express崩溃

C# 正在检查IIS Express上多个页面的HTTP状态:使IIS Express崩溃,c#,iis,optimization,iis-express,C#,Iis,Optimization,Iis Express,我正在编写一个简单的C控制台应用程序,它的主要任务是,当给定一组URL时,ping这些URL并报告是否返回了HTTP200OK结果。现实生活中的数据集在20000个URL的范围内进行测试,以验证大规模编辑没有破坏任何页面 当前,检查响应的代码如下所示: public UrlTestResult TestUrl(string url) { if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentNullExce

我正在编写一个简单的C控制台应用程序,它的主要任务是,当给定一组URL时,ping这些URL并报告是否返回了HTTP200OK结果。现实生活中的数据集在20000个URL的范围内进行测试,以验证大规模编辑没有破坏任何页面

当前,检查响应的代码如下所示:

public UrlTestResult TestUrl(string url)
{
    if (string.IsNullOrWhiteSpace(url))
    {
        throw new ArgumentNullException("url");
    }
    using (var client = new HttpClient())
    {
        try
        {
            Task<HttpResponseMessage> message = client.GetAsync(url);
            if (message == null || message.Result == null)
            {
                return new FailedUrlTestResult(url, "No response was returned.");
            }
            if (message.Result.StatusCode == HttpStatusCode.OK)
            {
                return new SuccessfulUrlTestResult(url);
            }
            return new FailedUrlTestResult(url, "{0}: {1}".Format((int)message.Result.StatusCode, message.Result.ReasonPhrase));
        }
        catch (Exception ex)
        {
            return new FailedUrlTestResult(url, "An exception occurred: " + ex);
        }
    }
}
public sealed class UrlTester : IUrlTester
{
    private readonly HttpClient httpClient = new HttpClient();

    public UrlTestResult TestUrl(string url)
    {
        if (string.IsNullOrWhiteSpace(url))
        {
            throw new ArgumentNullException("url");
        }

        try
        {
            Task<HttpResponseMessage> message = httpClient.GetAsync(url);
            if (message == null || message.Result == null)
            {
                return new FailedUrlTestResult(url, "No response was returned.");
            }
            if (message.Result.StatusCode == HttpStatusCode.OK)
            {
                return new SuccessfulUrlTestResult(url);
            }
            return new FailedUrlTestResult(url, "{0}: {1}".FormatCurrentCulture((int)message.Result.StatusCode, message.Result.ReasonPhrase));
        }
        catch (Exception ex)
        {
            return new FailedUrlTestResult(url, "An exception occurred: " + ex);
        }
    }

    public void Dispose()
    {
        if (httpClient != null)
        {
            httpClient.Dispose();
        }
    }
}
此代码适用于较小的数据集。即使我使用Parallel.ForEach而不是普通的ForEach来迭代URL集合,它的行为也很好。但是,在运行几分钟左右后,在解析20000数据集时,承载localhost的IIS Express将崩溃

我猜我的选择是:

用完IIS,看看是否有效 限制请求的数量,让IIS Express有机会呼吸。这里的技巧是限制多少 在更小的块中测试URL,类似于第二个选项 我想知道的是:

有没有比HttpClient更便宜的方法ping URL并获取其HTTP响应? 我是否应该考虑IIS或IIS Express的任何配置选项? 编辑:我发现IIS Express似乎只是内存不足。图中是发生碰撞的实例:


这意味着IIS Express保留了显然不需要的内存,因为一旦请求结束,我就不再关心它了。不过,我不知道这是否有助于解决我的问题。

我只是改为使用IIS运行localhost,而不是IIS Express。内存使用量大致相同,但在应用程序运行的十分钟内,它从未在任何时候崩溃。我还采纳了Gabi的意见/建议,并让HttpClient只实例化一次,而不是每次测试实例化一次。最后的代码如下所示:

public UrlTestResult TestUrl(string url)
{
    if (string.IsNullOrWhiteSpace(url))
    {
        throw new ArgumentNullException("url");
    }
    using (var client = new HttpClient())
    {
        try
        {
            Task<HttpResponseMessage> message = client.GetAsync(url);
            if (message == null || message.Result == null)
            {
                return new FailedUrlTestResult(url, "No response was returned.");
            }
            if (message.Result.StatusCode == HttpStatusCode.OK)
            {
                return new SuccessfulUrlTestResult(url);
            }
            return new FailedUrlTestResult(url, "{0}: {1}".Format((int)message.Result.StatusCode, message.Result.ReasonPhrase));
        }
        catch (Exception ex)
        {
            return new FailedUrlTestResult(url, "An exception occurred: " + ex);
        }
    }
}
public sealed class UrlTester : IUrlTester
{
    private readonly HttpClient httpClient = new HttpClient();

    public UrlTestResult TestUrl(string url)
    {
        if (string.IsNullOrWhiteSpace(url))
        {
            throw new ArgumentNullException("url");
        }

        try
        {
            Task<HttpResponseMessage> message = httpClient.GetAsync(url);
            if (message == null || message.Result == null)
            {
                return new FailedUrlTestResult(url, "No response was returned.");
            }
            if (message.Result.StatusCode == HttpStatusCode.OK)
            {
                return new SuccessfulUrlTestResult(url);
            }
            return new FailedUrlTestResult(url, "{0}: {1}".FormatCurrentCulture((int)message.Result.StatusCode, message.Result.ReasonPhrase));
        }
        catch (Exception ex)
        {
            return new FailedUrlTestResult(url, "An exception occurred: " + ex);
        }
    }

    public void Dispose()
    {
        if (httpClient != null)
        {
            httpClient.Dispose();
        }
    }
}

这个类的调用者利用C的using语句来确保HttpClient实例被正确处理。

您是否直接调用Parallel.ForEach中的TestUrl?HttpClient类的设计是为了能够安全地重用实例。请参阅此处的备注部分:因此,您不应根据url实例化HttpClient实例。@Gabi我已将代码更新为仅使用单个HttpClient实例。