Synchronization of remote files download Preamble: it's a self-assigned and pure syntetic task to learn (and remember what I already knew) C# threads and synchronization and data structures.

The original question was here https://stackoverflow.com/questions/16458937/synchronization-of-remote-files-download

The short task explanation:

Let's say I have a dictionary &lt;string, string&gt; that represents a path (http) to a file by some key, ie:

foo =&gt; http://domain.tld/file1
bar =&gt; http://domain2.tld/file2


And I'd like to implement a class that will implement an interface with 2 methods:

String Rand();
String Get(String key);


The first method would pick the file randomly from all the available, and the Get would return a particular file, or to be precise - local path to a downloaded file.

The class should be thread-safe, so that if several threads request the same key with Get() or the Rand() picks the same item - then only one thread should actually download a file to a local drive, or the path should be retrieved immediately if a file has already been downloaded.

My proof of concept solution is:

class Downloader
{
    private readonly IDictionary&lt;string, string&gt; _map;
    private IDictionary&lt;string, string&gt; _storage = new Dictionary&lt;string, string&gt;();
    private ConcurrentDictionary&lt;string, Task&lt;string&gt;&gt; _progress = new ConcurrentDictionary&lt;string,Task&lt;string&gt;&gt;();

    public Downloader(IDictionary&lt;string, string&gt; map)
    {
        _map = map ?? new Dictionary&lt;string, string&gt;();
    }

    public string Get(string key)
    {
        if (_storage.ContainsKey(key))
        {
            return _storage[key];
        }

        Task&lt;string&gt; task;
        if (_progress.TryGetValue(key, out task))
        {
            return task.Result;
        }

        task = _retrieveFile(key);

        if (!_progress.TryAdd(key, task))
        {
            return Get(key);
        }

        task.Start();
        _storage[key] = task.Result;
        return task.Result;
    }

    private Task&lt;string&gt; _retrieveFile(string key)
    {
        string path;

        if (!_map.TryGetValue(key, out path))
        {
            throw new ArgumentException("The specified key wasn't found");
        }

        return new Task&lt;string&gt;(k =&gt;
        {
            Console.WriteLine("Started retrieving {0}", k.ToString());
            System.Threading.Thread.Sleep(3000);
            Console.WriteLine("Finished retrieving {0}", k.ToString());
            return k.ToString() + " local path";
        }, path);
    }
}


The copy is at http://pastebin.com/LJnK7FB6

How could I make it better? Any particular problems with the code?

In the comments @I4V pointed out to some problems at https://stackoverflow.com/questions/16458937/synchronization-of-remote-files-download#comment23617420_16460673 but seems like I'm missing the point
If you change _retrieveFile to return a Task that's already started, you could simplify the whole Get() into just:

return _progress.GetOrAdd(key, _retrieveFile).Result;


Also, it seems that Downloader with empty map doesn't make sense, so you should check for that in your constructor, instead of using ??.