我用它来下载文件......
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下载第一块数据。在那段时间,用户界面似乎在等待用户输入等等......
有没有办法获得有关这段时间内发生的事情的更多信息?我确定它正在解析主机,发送用户/通行证信息等等。我希望得到一些进展,这样我就可以更新我的用户界面。
答案 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();
我的输出如下:
调用TraceListener时会写入黄色+
。其余的是从WebClient引发的正常事件中收到的数据。
请记住,监听器是应用程序的全局。因此,如果您有使用System.Net类的后台线程,那么您也会为这些线程获取事件。要么解析消息以实现某种关联,要么变得脆弱,请使用其他ProgressEvents实现自己的WebClient。