WCF(.NET 4.0)は、WebページのHTMLを取得する機能を提供しますか?そうでない場合、.NET 4.0でこれを行うための最良の方法は何ですか?
2 に答える
            1        
        
		
WebClientを使用して Web ページの HTML を取得できます
using (WebClient web = new WebClient())
{
    var data = web.DownloadData(myURL);
}    
WebClient には、ダウンロード時間を設定できない、進行状況イベントに一貫性がないなど、いくつかの制限があります。それを改善する独自のサブクラスを作成しました。役に立つ場合のコードを次に示します。私が取り組んでいるコードにはバグがあることに注意してください (イベント ハンドラー中に破棄される WebClient サブクラスを参照してください。結果は ObjectDisposedExceptionです)。バグを簡単に修正するには、質問に記載されている行の周りに try/catch を配置しますが、その質問の中心的な問題を理解しようとしています。
public class MyWebClient : WebClient, IDisposable
{
    public int Timeout { get; set; }
    public int TimeUntilFirstByte { get; set; }
    public int TimeBetweenProgressChanges { get; set; }
    public long PreviousBytesReceived { get; private set; }
    public long BytesNotNotified { get; private set; }
    public string Error { get; private set; }
    public bool HasError { get { return Error != null; } }
    private bool firstByteReceived = false;
    private bool success = true;
    private bool cancelDueToError = false;
    private EventWaitHandle asyncWait = new ManualResetEvent(false);
    private Timer abortTimer = null;
    private bool isDisposed = false;
    const long ONE_MB = 1024 * 1024;
    public delegate void PerMbHandler(long totalMb);
    public event PerMbHandler NotifyMegabyteIncrement;
    public MyWebClient(int timeout = 60000, int timeUntilFirstByte = 30000, int timeBetweenProgressChanges = 15000)
    {
        this.Timeout = timeout;
        this.TimeUntilFirstByte = timeUntilFirstByte;
        this.TimeBetweenProgressChanges = timeBetweenProgressChanges;
        this.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(MyWebClient_DownloadFileCompleted);
        this.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MyWebClient_DownloadProgressChanged);
        abortTimer = new Timer(AbortDownload, null, TimeUntilFirstByte, System.Threading.Timeout.Infinite);
    }
    protected void OnNotifyMegabyteIncrement(long totalMb)
    {
        if (NotifyMegabyteIncrement != null) NotifyMegabyteIncrement(totalMb);
    }
    void AbortDownload(object state)
    {
        cancelDueToError = true;
        this.CancelAsync();
        success = false;
        Error = firstByteReceived ? "Download aborted due to >" + TimeBetweenProgressChanges + "ms between progress change updates." : "No data was received in " + TimeUntilFirstByte + "ms";
        asyncWait.Set();
    }
    void MyWebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        if (cancelDueToError || isDisposed) return;
        long additionalBytesReceived = e.BytesReceived - PreviousBytesReceived;
        PreviousBytesReceived = e.BytesReceived;
        BytesNotNotified += additionalBytesReceived;
        if (BytesNotNotified > ONE_MB)
        {
            OnNotifyMegabyteIncrement(e.BytesReceived);
            BytesNotNotified = 0;
        }
        firstByteReceived = true;
        if (!isDisposed) abortTimer.Change(TimeBetweenProgressChanges, System.Threading.Timeout.Infinite);
    }
    public bool DownloadFileWithEvents(string url, string outputPath)
    {
        asyncWait.Reset();
        Uri uri = new Uri(url);
        this.DownloadFileAsync(uri, outputPath);
        asyncWait.WaitOne();
        return success;
    }
    void MyWebClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        if (cancelDueToError || isDisposed) return;
        asyncWait.Set();
    }
    protected override WebRequest GetWebRequest(Uri address)
    {            
        var result = base.GetWebRequest(address);
        result.Timeout = this.Timeout;
        return result;
    }
    void IDisposable.Dispose()
    {
        isDisposed = true;
        if (asyncWait != null) asyncWait.Dispose();
        if (abortTimer != null) abortTimer.Dispose();
        base.Dispose();
    }
}
于 2012-08-24T17:15:41.873   に答える