我正在从FTP站点(Async)下载文件,需要更新进度条。我已经阅读了MS文档,声明可以做到这一点是WebClient类的GetWebRequest()是ovverriden所以'UsePassive'属性被设置为'false'。我已经这样做但是'DownloadProgressChanged'事件参数ProgressPercentage总是=='0'。
有人可以告诉我如何让这个参数开始返回值吗?
这是下载方法:
FTPClient request = new FTPClient();
request.Credentials = new NetworkCredential(user, password);
request.DownloadProgressChanged += UpdateProgress;
request.DownloadFileAsync(ftpepath,destinationpath);
这是FTPClient(我将覆盖GetWebRequest()):
class FTPClient : WebClient
{
protected override WebRequest GetWebRequest(System.Uri address)
{
FtpWebRequest req = (FtpWebRequest) base.GetWebRequest(address);
req.UsePassive = false;
return req;
}
}
如果有帮助我的回调:
void UpdateProgress(object sender, DownloadProgressChangedEventArgs e)
{
dwnProgress.Value = e.ProgressPercentage;
dwnprcnt.Text = PercentProgress.ToString() + "%";
}
答案 0 :(得分:3)
UsePassive
用于“确定”在进行文件传输连接时充当服务器的人员,因此它不应与传输的实际状态有任何关系。请问你在哪里看过这个?
可能是那个
您可以在UpdateProgress中设置断点并查看任何e属性中的任何内容吗?
作为旁注,由于您正在下载文件异步,因此另一个线程用于实际下载。在您的事件方法中,您可能希望执行以下操作:
void UpdateProgress(object sender, DownloadProgressChangedEventArgs e) {
setProgress(e.ProgressPercentage);
setText(e.ProgressPercentage.ToString() + "%");
}
private void setProgress(int progress){
if (dwnProgress.InvokeRequired) {
dwnProgress.Invoke(new Action<int>(setProgress), progress);
return;
}
dwnProgress.Value = progress;
}
private void setText(string text) {
if (dwnprcnt.InvokeRequired) {
dwnprcnt.Invoke(new Action<string>(setText), text);
return;
}
dwnprcnt.Text = text;
}
将把setmethods排队到UI线程。
答案 1 :(得分:2)
我想对上述帖子发表评论,但我太新了:(
在覆盖Web请求方法时引用MSDN:
http://msdn.microsoft.com/en-US/library/system.net.webclient.downloadprogresschanged(v=vs.80).aspx
但是,如果您的FTP服务器未设置为接受活动连接,那么在回答OP问题时,设置WebClient.UsePassive = false将没有任何区别。
编辑:我在我的项目上启用了System.Net.Tracing并尝试了被动模式和主动模式,并且不仅两个都按预期工作... TotalBytes仍然是-1所以我的想法是MSDN上的注释错误或我们遗失了什么DownloadFileProgressChangedEventArgs确实包含收到的总字节数,如果你知道文件大小,你可以自己计算。
可能有更好的方法...但我使用快速FtpWebRequest获取文件大小,然后将其传递给DownloadProgressCallback方法以更新进度条。
上面的海报没有提到的是你的更新进度方法必须调用控件,因为它是由DownloadFileAsync创建的线程调用的,你只能从创建它的线程中更改控件。
您应该使用调度程序进行控制,例如
if (!myCheckBox.Dispatcher.CheckAccess())
{
myCheckBox.Dispatcher.BeginInvoke(new Action(
delegate()
{
myCheckBox.IsChecked = true;
}
));
}
else
{
myCheckBox.IsChecked = true;
}