如何在连接时从WebClient.DownloadDataAsync()获取更多信息?

时间:2016-02-29 16:25:25

标签: c# winforms .net-4.0 webclient

我用它来下载文件......

WebClient wc = new WebClient();
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadDataCompleted +=new DownloadDataCompletedEventHandler(wc_DownloadDataCompleted);
wc.DownloadDataAsync(new Uri("http://www.example.com/myfile.exe"));

我有像这样的事件处理程序......

private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    //There has been some type of progress with the download
}

private void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
    //The download has finished
}

一切都很棒!我遇到的问题是我调用DownloadDataAsync()时的延迟。一旦我打电话,似乎我没有任何类型的进度报告,直到WebClient下载第一块数据。在那段时间,用户界面似乎在等待用户输入等等......

有没有办法获得有关这段时间内发生的事情的更多信息?我确定它正在解析主机,发送用户/通行证信息等等。我希望得到一些进展,这样我就可以更新我的用户界面。

1 个答案:

答案 0 :(得分:1)

如果您不想重新实现默认WebClient以在DNS查找完成时发送事件,则会协商安全通道,正在打开已连接的套接字,http-header是交换,仅举几例,你可以在winclient的场景中使用滥用内置日志记录。

这个想法如下:您配置一个自定义TraceListener,它将由System.Net TraceSource记录的消息提供。如果将tracesource配置为详细日志记录,则会收到消息,指示正在进行的任何连接的进度。监听器为您在应用程序中可以订阅的每条消息引发事件。

以下是TraceListener

的实施
/// <summary>
/// holds the message being send to the listener
/// </summary>
public class DetailedProgressEventArgs:EventArgs
{
    public string Message;
    public DetailedProgressEventArgs(string msg)
    {
        Message = msg;
    }
}

/// <summary>
/// enables sending events when a log message is written
/// </summary>
/// <param name="sender">the instance that sends the event</param>
/// <param name="e">the actual message</param>
public delegate void DetailedProgressEventHandler(object sender, DetailedProgressEventArgs e);

/// <summary>
/// Used as a TraceListener and wired in the app.config to receive System.Net messages
/// </summary>
public class DetailedProgressListener : TraceListener
{
    // wire the event handlers here
    static public event DetailedProgressEventHandler ProgressChanged;

    public override void Write(string message)
    {
        // let's do nothing
    }

    /// <summary>
    /// rasies a progessChanged event for every message
    /// </summary>
    /// <param name="message"></param>
    public override void WriteLine(string message)
    {
        var pch = ProgressChanged;
        if (pch!=null)
        {
            pch.Invoke(this, new DetailedProgressEventArgs(message));
        }
    }
}

这是您需要添加到app.config以获取diagnostic logging enabled

的内容
<configuration>
    <system.diagnostics>
      <sources>
        <source name="System.Net" tracemode="includehex" maxdatasize="1024">
          <listeners>
            <add name="ProgressListener"/>
          </listeners>
        </source>
      </sources>
      <switches>
        <add name="System.Net" value="Verbose"/>
      </switches>
      <sharedListeners>
        <add name="ProgressListener"
          type="YourApp.DetailedProgressListener, YourApp" />
      </sharedListeners>
      <trace autoflush="true"/>
    </system.diagnostics>
</configuration>

我为控制台应用程序创建了一个小实现示例。我假设这提供了足够的细节以使其适应您自己的实现方案,使用多行文本框或进度条:

Console.BackgroundColor = ConsoleColor.Black;

// handle hidden progress
DetailedProgressEventHandler progress = (s, e) =>
    {
        var old = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.Write("+");
        Debug.WriteLine(e.Message);
        Console.ForegroundColor = old;
    };

// hookup the event
DetailedProgressListener.ProgressChanged += progress;

using(var wc = new WebClient())
{
    wc.DownloadProgressChanged += (s, e) => {
        // stop once we have normal progress
        DetailedProgressListener.ProgressChanged -= progress;

        var old = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.DarkRed;
        Console.Write(e.BytesReceived);
        Console.Write(" ,");
        Console.ForegroundColor = old;
    };
    wc.DownloadDataCompleted += (s, e) =>
    {
        var old = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine(" Done");
        Console.ForegroundColor = old;
    };

    wc.DownloadDataAsync(new Uri("https://stackoverflow.com"));
}
Console.ReadLine();

我的输出如下:

output from progress class

调用TraceListener时会写入黄色+。其余的是从WebClient引发的正常事件中收到的数据。

请记住,监听器是应用程序的全局。因此,如果您有使用System.Net类的后台线程,那么您也会为这些线程获取事件。要么解析消息以实现某种关联,要么变得脆弱,请使用其他ProgressEvents实现自己的WebClient。