• Welcome to Valhalla Legends Archive.
 

Synchronous file downloading

Started by Stealth, February 23, 2004, 06:32 PM

Previous topic - Next topic

Stealth

I would like StealthBot to download a news file (simple, one-line .txt file containing formatted data). This is fairly easily accomplished using INet, or the URLDownloadToFile() API call. However, I need the file to be downloaded without interfering with the functionality of the bot at all or it won't meet my standards.

The current method, a standard INet control, hangs the rest of the bot's operations while it downloads. This isn't acceptable. I also attempted to create a class module to handle the task using URLDownloadToFile() -- the same problem occurs. URLDownloadToFile() within the class hangs the program until finished. Is it possible to download the file synchronously, perhaps by multithreading it? If necessary, I can port the class module's code to a standard module so that it can be used with the AddressOf operator.

Additionally, I will post the code to either the static-reference subroutine or the class module if necessary.
- Stealth
Author of StealthBot

K

The easiest way to trick VB into multithreading is to do something like:


// to download file:
Form1_Load() // or whenever
{
  tmrDownload.Enabled = True
}

// Timer Proc
tmrDownload_Tick()
{
  URLDownloadToFile(/ * ..... */ )
  MessageBox(0, "File Download Complete", "", MB_OK)
  DoThingsWithDownloadedFile()
  tmrDownload.Enabled = False
 
}


Alternatively, I believe the INET control does have the ability to do asynchronous downloading.  I'm not sure how, though.

Stealth

The timer idea worked beautifully. Thank you. :)
- Stealth
Author of StealthBot

UserLoser.

Could just set up a socket, connect, and request the file to the news, then just dump all the recieved text to a file

Stealth

I ended up writing a module that uses SetTimer and KillTimer to create a short-lived timer thread within which URLDownloadToFile() can do its thing peacefully and without interfering. It works and it's low-overhead, so it seems to be all good. =)
- Stealth
Author of StealthBot

o.OV

#5
mm..
You already have a working solution but..
I'll add to the thread anyways.

One alternate method involves using UserControls.
I suck with my object oriented programming but..
here is an example project.



'FORM1

Option Explicit

Public fromFile As String, toFile As String

Private Sub Form_Load()
   'specify the url to download from
   fromFile = "http://forum.valhallalegends.com/bbsImages/vl_logo_new.jpg"
   'specify where to output the file to
   toFile = App.Path & "\Temp.jpg"
   'start the download
   Load Form2
End Sub

Private Sub Form_Unload(Cancel As Integer)
   'abort download
   Unload Form2
End Sub




'FORM2

'nothing here _
don't forget to add the UserControl to form2 using ToolBox




'USERCONTROL1

Option Explicit

Private Type SHFILEOPSTRUCT
   hWnd As Long
   wFunc As Long
   pFrom As String
   pTo As String
   fFlags As Integer
   fAnyOperationsAborted As Long
   hNameMappings As Long
   lpszProgressTitle As Long
End Type

Dim Operation As SHFILEOPSTRUCT

Private Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long

Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)
   If AsyncProp.PropertyName = 69 Then
       With Operation
           .wFunc = 1
           .pFrom = AsyncProp.Value
           .pTo = Form1.toFile
           .fFlags = &H100
       End With
       SHFileOperation Operation
       MsgBox Form1.toFile
       Unload Form2
   End If
End Sub

Private Sub UserControl_Initialize()
   UserControl.AsyncRead Form1.fromFile, vbAsyncTypeFile, 69
End Sub

If the facts don't fit the theory, change the facts. - Albert Einstein

Adron

I don't see why using SetTimer and KillTimer is supposed to help. Don't they call in the context of the original thread, blocking that?

Also, as far as I can remember, the Inet transfer control operates just fine asynchronously, with events for when you receive some data.

Stealth

#7
Quote from: Adron on February 24, 2004, 03:56 PM
I don't see why using SetTimer and KillTimer is supposed to help. Don't they call in the context of the original thread, blocking that?

Also, as far as I can remember, the Inet transfer control operates just fine asynchronously, with events for when you receive some data.

You may be correct about the threading -- my testing of whether or not it actually stalled the rest of the operations wasn't very scientific.

In any event, I rewrote it as follows:

'Form_Load()
INet.Execute "http://www.cold-chaos.net/stealth/getver.php", "GET"


Private Sub INet_StateChanged(ByVal State As Integer)
   If (State = icResponseCompleted) Then
       Call HandleNews(INet.GetChunk(1024, icString))
   End If
End Sub
- Stealth
Author of StealthBot