如何在连接时从 WebClient.DownloadDataAsync() 获取更多信息?
How can I get more information from WebClient.DownloadDataAsync() while it's connecting?
我用这个来下载文件...
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 下载第一块数据之前,我似乎根本没有任何类型的进度报告。在那个时候 UI 看起来像是在等待用户输入等...
有什么方法可以获取有关此时间范围内发生的事情的更多信息?我确定它正在解析主机、发送 user/pass 信息等。我希望获得一些进展,以便我可以更进一步地更新我的 UI。
如果您不想 re-implement 默认 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>
我为控制台应用程序创建了一个小的实施示例。我假设这提供了足够的细节以使其适应您自己的实施方案,使用 multi-line 文本框或进度条:
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://whosebug.com"));
}
Console.ReadLine();
我的输出如下所示:
黄色+
是调用TraceListener时写的。其余的是从 WebClient 引发的 正常 事件接收的数据。
请记住,侦听器对于应用程序是全局的。因此,如果您有使用 System.Net 类 的后台线程,您也将获得这些事件。解析消息以实现某种相关性,或者如果它变得脆弱,则使用额外的 ProgressEvents 实现您自己的 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 下载第一块数据之前,我似乎根本没有任何类型的进度报告。在那个时候 UI 看起来像是在等待用户输入等...
有什么方法可以获取有关此时间范围内发生的事情的更多信息?我确定它正在解析主机、发送 user/pass 信息等。我希望获得一些进展,以便我可以更进一步地更新我的 UI。
如果您不想 re-implement 默认 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>
我为控制台应用程序创建了一个小的实施示例。我假设这提供了足够的细节以使其适应您自己的实施方案,使用 multi-line 文本框或进度条:
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://whosebug.com"));
}
Console.ReadLine();
我的输出如下所示:
黄色+
是调用TraceListener时写的。其余的是从 WebClient 引发的 正常 事件接收的数据。
请记住,侦听器对于应用程序是全局的。因此,如果您有使用 System.Net 类 的后台线程,您也将获得这些事件。解析消息以实现某种相关性,或者如果它变得脆弱,则使用额外的 ProgressEvents 实现您自己的 WebClient。