0

I am creating an application which on startup (MainWindow loaded) starts a BackgroundWorker, which on DoWork checks whether there is a newer version of the file (DatasSource for an Autocompletebox) available. If so, I download and merge this with the existing file and create a new file.

Now I want to do this on startup and also periodically (like 30 minutes). So I created a threading.Timer [it's a private member in MainWindow class] and initialize it in RunWorkerCompleted of the backgroundWorker (as mentioned above). The timer goes to the callback successfully but at the file download code (just a fyi, a different namespace and different class) it just terminates and I can't figure out why?

I have tried using Windows.Timers.Timer, ThreadPool.RegisterWaitForSingleObject() but no luck...

Can anyone point me to the right direction? I am open to any solution.

Download code:

Public Sub MergeHistoryFile()
  /*Check the directory if there are any downloaded files(.tmp);if there are;just   delete them*/
 /*some code which checks if file on web is modified;if yes download file*/ 
Try 
  Dim waiter As Threading.AutoResetEvent = New AutoResetEvent(False)
  _downloader = New WebClient()
  AddHandler _downloader.DownloadDataCompleted, AddressOf Me.DownloaderFileCompleted
  _downloader.DownloadDataAsync(New Uri(path_file), waiter)
  waiter.WaitOne() 
Catch ex As Exception 
  Throw ex 
End Try

/*some more code which checks if there something new in the downloaded file;if yes merge the local and the downloaded file reinitialize the autocomplebox*/
End Sub

Private _downloadCancelled As Boolean = False
Private Sub DownloaderFileCompleted(ByVal sender As Object, ByVal e As System.Net.DownloadDataCompletedEventArgs)
    If IsNothing(e.Error) Then
        If Not (IsNothing(e.Result)) Then
            Using fs As New FileStream(Path.Combine(HistoryPath, "_tempDownladedFile.tmp"), FileMode.CreateNew)
                fs.Write(e.Result, 0, e.Result.Count)
            End Using
            CType(e.UserState, Threading.AutoResetEvent).Set()
        End If
    Else
        _downloadCancelled = True
        _downloader.CancelAsync()
    End If
End Sub
Sparsh Gupta
  • 51
  • 11
  • See http://stackoverflow.com/questions/2663893/writing-file-from-httpwebrequest-periodically-vs-after-download-finishes – Mihai8 Jun 14 '13 at 12:12
  • 3
    Does this need to be done while the app is running or is this something that will get done on a central server? If so, you could create a batch program and have something like a Cron job or Window's Task Scheduler to kick it off every 30 minutes. – jason Jun 14 '13 at 12:20
  • 1
    When it terminates does it throw an exception? Do you know *where* it terminates? Perhaps you could show us the download code so that we can get an idea of what you're doing. Without that, we'd just be guessing. – Jim Mischel Jun 14 '13 at 13:41
  • Enclose your download routine into try { } catch { } block and log exception somewhere. – Ondrej Svejdar Jun 14 '13 at 15:06
  • Yes,this should work while the application is running.I don't want to create another service just for this feature. I don't get any exception; the program just goes back to the UI and the next time it terminates at a different section – Sparsh Gupta Jun 14 '13 at 16:25
  • I don't get any exception unfortunately but here is my download code : – Sparsh Gupta Jun 14 '13 at 16:27
  • Does it actually trigger a HTTP request or does it fail to start that. – user1937198 Jun 14 '13 at 16:48
  • When the first time the timercallback is called it executes the httprequest successfully.it just quits at the webclient download async.the next timercallback it exits at httprequest itself – Sparsh Gupta Jun 14 '13 at 17:06
  • One problem is that you'll wait forever if there is an error. You never set the wait event except in the success case. In addition, I don't see why you're doing an async call here if all you're going to do is wait for it. async-and-wait has the same effect as calling the synchronous method ... it's just more complicated. Finally, `WebClient` is `IDisposable`, so you should put it in a `Using` http://msdn.microsoft.com/en-us/library/htd05whh(v=vs.110).aspx – Jim Mischel Jun 14 '13 at 20:17
  • I tried to use the synchronous way of downloading the data and creating the file;but still no success.I forgot to mention that before downloading the file i check if there are any (temporary files download);if there are i just delete them;that's why FileMode.CreateNew. – Sparsh Gupta Jun 16 '13 at 11:33
  • Any solution..I am dumbfounded here. Just can't figure out why is this happening.The code works successfully first time,but the next time its unable to download. – Sparsh Gupta Jun 17 '13 at 04:35
  • @SparshGupta: See my answer. It works the first time and then fails on subsequent tries because of the `FileMode` you're using. – Jim Mischel Jun 17 '13 at 13:49
  • @JimMischel: Hi, I even tried to do FileMode.Create but still it doesn't work; the code just goes back to the GUI without any exception. – Sparsh Gupta Jun 18 '13 at 07:26
  • http://stackoverflow.com/questions/5827030/httpwebrequest-times-out-on-second-call – Sparsh Gupta Jun 27 '13 at 06:48

1 Answers1

0

There are several problems with this code, as I pointed out in my comment.

I think your primary problem is that when you create the file, you're passing FileMode.CreateNew, which is going to fail if the file already exists. As the documentation says:

CreateNew Specifies that the operating system should create a new file. This requires FileIOPermissionAccess.Write permission. If the file already exists, an IOException exception is thrown.

You probably want FileMode.Create.

So what happens is that the FileStream constructor throws an exception, which causes your DownloadFileCompleted method to exit without ever setting the event that tells the caller to stop waiting.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351