如果您不想重新实现默认 WebClient 以在 DNS 查找完成时发送事件、协商安全通道、打开连接的套接字、交换 http-headers 以命名一些,您可以在使用 winclient 的场景中滥用内置日志记录。
想法如下:您配置一个自定义 TraceListener,它将由 System.Net 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();
我的输出如下所示:
黄色的+ 是在调用 TraceListener 时写入的。其余的是从 WebClient 引发的 normal 事件中接收到的数据。
请记住,侦听器对于应用程序是全局的。因此,如果您也有使用 System.Net 类的后台线程,您还将获得这些事件。解析消息以实现某种关联,或者如果这变得脆弱,则使用额外的 ProgressEvents 实现您自己的 WebClient。