0

I am pulling a JSON string from a web page, which contains a list of objects. Within each object are two strings, which both contain a link to an image. I want to download this image locally.

I'm currently using an async function which is fired every few seconds, and looks for any new objects within the JSON that weren't previously in the list, gets the image links, and downloads them like so:

using (WebClient webClient = new WebClient())
{
    await webClient.DownloadFileTaskAsync(new Uri(object.AvatarImage), System.IO.Directory.GetCurrentDirectory() + "\\Elements" + "\\" + object.PostID.Replace(':', '-') + "_avatar.png");
}

using (WebClient webClient = new WebClient())
{
    await webClient.DownloadFileTaskAsync(new Uri(object.Media), System.IO.Directory.GetCurrentDirectory() + "\\Elements" + "\\" + object.PostID.Replace(':', '-') + "_media.png");
}

This works OK until I get a larger volume of images coming in, at which point I sometimes get the error:

The process cannot access the file 'path' because it is being used by another process.

I'm not manipulating the files anywhere else, and although the image path does get bound to an image control, I still get the same error if I break the binding.

What could be causing this?

Luke4792
  • 455
  • 5
  • 19

1 Answers1

1

Do you trigger the download with an System.Timers.Timer? Have you set the timer to AutoReset=true? Then maybe the download method is called a second time before the first call is complete.

From https://msdn.microsoft.com/en-us/library/system.timers.timer.autoreset(v=vs.110).aspx

"If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant."

One Solution would be to set AutoReset to false and always call the timer Start() method after the download is finished. It is important that you do sufficient error handling so that the call of the Start() method is not prevented by an unhandled exception.

  • I'm using System.Windows.Forms.Timer at the moment. Is it worth switching over? – Luke4792 Feb 28 '18 at 10:20
  • You don't need to switch over. As I could see in the documentation the System.Windows.Forms.Timer is single threaded. But you mentioned that you are using an async function to download the images. I think you have to use a blocking function. Can you post the code parts from the timer elapsed event handler that shows how you call the download method? – Raphael Hinterndorfer Feb 28 '18 at 11:23