【发布时间】:2017-02-01 06:08:41
【问题描述】:
所以,我一直在努力解决这个问题已经有一段时间了。我是一个业余程序员,所以我并不总是知道自己做错了什么。
总之,我最近项目的前提:
我和我的朋友们经常玩《我的世界》,但他们并不是很聪明,而且我们并不总是在附近获取模组并向他们发送链接等等。所以我想我应该编写一些程序来自动下拉模组,以便它们与服务器同步并同时获取服务器数据。
我正在使用免费的 FTP 主机,但我认为这不是问题所在,原因将变得很清楚。
基本上,我想使用进度条和理想的标签来指示整个数据块的进度(所有模块一起......不超过 1GB - 小得多)。但是,我似乎遇到了一些关于 Async 选项的问题:
它会随机选择不下载它应该下载的文件
在声称完整之前,它可能不会完整下载文件
当 msgbox 触发说它已完成下载所有项目时,进度条可能已满 50%。
但是,由于在同步使用 Webclient 时不存在进度报告事件,进度条不起作用,但当我在 BGworker 中运行同步时,它每次都能正确下载。但是,我失去了进度报告,这很重要....
所以,基本上:
- 有没有更好的方法来实现这一点?
这是我在准备好之前需要开始工作的最后一块,所以我真的很想尝试这样做。感谢您的帮助!
编辑:用代码更新:
Public Function GetDownloadSize(ByVal URL As String) As Long
Dim request As Net.FtpWebRequest = DirectCast(Net.WebRequest.Create(URL), Net.FtpWebRequest)
request.Method = Net.WebRequestMethods.Ftp.GetFileSize
request.Credentials = New Net.NetworkCredential(dl_user, dl_pass)
Dim response As Net.FtpWebResponse = DirectCast(request.GetResponse(), Net.FtpWebResponse)
Dim fileSize As Long = response.ContentLength
Return fileSize
End Function
Private Sub btn_sync_Click(sender As Object, e As EventArgs) Handles btn_sync.Click
Dim cont As DialogResult = MsgBox("Continue? " + (total_dl_size / 1000).ToString("N0") + " KB remain to be downloaded.", MsgBoxStyle.YesNo, "CAUTION!")
If cont = DialogResult.No Then
tb_warnings.AppendText("-ERR: User declined to synchronize files. Restart the application to sync.")
tb_warnings.AppendText(ControlChars.NewLine)
Label3.BackColor = Color.Firebrick
Return
End If
btn_sync.Enabled = False
btn_scan.Enabled = false
tb_warnings.AppendText("-Deleting outmoded/unused mods. Protected mods will be kept.")
For Each i As fdata_obj In deleted_files
My.Computer.FileSystem.DeleteFile(mc_dir + "\mods\" + i.name)
Next
tb_warnings.AppendText(ControlChars.NewLine)
tb_warnings.AppendText("-Deleting mod subdirectories to ensure no conflicts.")
tb_warnings.AppendText(ControlChars.NewLine)
For Each d In My.Computer.FileSystem.GetDirectories(mc_dir + "\mods")
My.Computer.FileSystem.DeleteDirectory(d, FileIO.DeleteDirectoryOption.DeleteAllContents)
Next
initialize_download()
End Sub
Private Sub initialize_download()
Dim wc As New System.Net.WebClient() ' SORRY, ASSUME THIS IS A PUBLIC VAR SO IT CAN BE REFERENCED ACROSS ITS OTHER METHODS
AddHandler wc.DownloadProgressChanged, AddressOf OnDownloadProgressChanged
AddHandler wc, AddressOf OnFileDownloadCompleted
Dim usr As String = "randouser"
Dim pass As String = "randopass"
For Each s In (From dl As fdata_obj In new_files Select dl_server + "/mods/" + mods_dir + "/" + dl.name).ToList
downloads.Enqueue(s)
Next
wc.Credentials = New Net.NetworkCredential(usr, pass)
Dim urix As String = downloads.Dequeue
Try
wc.DownloadFileasync(New Uri(urix), mc_dir + "\mods\" + IO.Path.GetFileName(urix))
Catch ex As Exception
MsgBox(ex.Message)
If tb_warnings.InvokeRequired = True Then
tb_warnings.Invoke(New tb_updater(AddressOf tb_update), "-ERR: Could not download file: " + urix, urix)
Else
tb_warnings.AppendText("-ERR: Could not download file: " + IO.Path.GetFileName(urix))
tb_warnings.AppendText(ControlChars.NewLine)
End If
end try
End Sub
Private Sub OnDownloadProgressChanged(ByVal sender As Object, ByVal e As System.Net.DownloadProgressChangedEventArgs)
MsgBox("This is happening!")
total_dl = total_dl + e.BytesReceived
Dim percentage As Integer = (CType((total_dl / total_dl_size), Integer) * 100)
if percentage > 100 then
percentage = 100
endif
prog_update(percentage)
End Sub
delegate sub progress_update(byval prog as integer)
' POTENTIAL ISSUES HERE???????
private sub prog_update(byval prog as integer)
if progressbar1.invokerequired then
progressbar1.invoke(new prog_update(addressof progress),prog)
else
progressbar1.value = prog
Private Sub OnFileDownloadCompleted(ByVal sender As Net.WebClient, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
If e.Cancelled Then
MsgBox(e.Cancelled)
ElseIf Not e.Error Is Nothing Then
MsgBox(e.Error.Message)
Else
if downloads.count > 0 then
Dim urix As String = downloads.Dequeue
Try
wc.DownloadFileasync(New Uri(urix), mc_dir + "\mods\" + IO.Path.GetFileName(urix))
Catch ex As Exception
MsgBox(ex.Message)
If tb_warnings.InvokeRequired = True Then
tb_warnings.Invoke(New tb_updater(AddressOf tb_update), "-ERR: Could not download file: " + urix, urix)
Else
tb_warnings.AppendText("-ERR: Could not download file: " + IO.Path.GetFileName(urix))
tb_warnings.AppendText(ControlChars.NewLine)
End If
End Try
End If
End Sub
【问题讨论】:
-
我上次检查时
WebClient运行良好。请向我们展示您的代码。 -
@VisualVincent #1:不错的用户名,#2:编辑帖子以显示代码。该委托函数调用调用可能略有偏差,因为我正在重写这段代码而没有 IDE 的好处并且不太记得格式。请放心,我的原始代码中的调用模板是正确的。
-
1: 谢谢 ;) 2: 好的,我先启动我的电脑,然后我会尝试代码。
-
你真的不应该这样分享你的密码,即使没有任何价值。请删除评论,我有自己的 FTP 服务器,我可以试试。
-
尝试并找出问题可能需要我大约一两个小时,所以请耐心等待。 :)
标签: vb.net multithreading winforms asynchronous webclient