public string GetMetaData(string key, out bool outError)
{
if (!_metaDataKeys.ContainsKey(key))
throw new InvalidOperationException(string.Format("Meta data key {0} is not supported or does not exist.", key));
outError = false;
var error = false;
try
{
if (_pendingTasks.ContainsKey(key))
{
Debug.WriteLine("Waiting for pending {0}", key);
return
_pendingTasks[key].ContinueWith(x =>
{
Debug.WriteLine("Pending {0} completed", key);
if (_cachedValues.ContainsKey(key))
return _cachedValues[key];
return null;
})
.Result;
}
if (!_attempts.ContainsKey(key))
_attempts[key] = 0;
if (!_cachedValues.ContainsKey(key))
{
var uri = serviceUrl + _metaDataKeys[key];
Debug.WriteLine("Requesting {0}", uri);
var tokenSource = new CancellationTokenSource();
var ct = tokenSource.Token;
Stream responseStream = null;
var task1 =
_pendingTasks[key] =
Task.Factory.StartNew(() =>
{
if (++_attempts[key] > 10)
_cachedValues[key] = key + "_MaxAttemptsExceeded";
var task =
Task.Factory.StartNew(() =>
{
try
{
responseStream =
WebRequest.Create(uri)
.GetResponse()
.GetResponseStream();
}
catch (Exception)
{
error = true;
}
}, ct);
if (!task.Wait(2000))
tokenSource.Cancel();
if (responseStream != null)
{
var s = new StreamReader(responseStream, true).ReadToEnd();
if (!string.IsNullOrEmpty(s))
{
_cachedValues[key] = s;
_attempts[key] = 0;
}
else
error = true;
}
else
error = true;
});
var result = task1
.ContinueWith(x =>
{
try
{
_pendingTasks.Remove(key);
}
catch (Exception) { }
if (error || !_cachedValues.ContainsKey(key))
{
error = true;
return "error_" + key;
}
Debug.WriteLine(string.Format("Got {0}: {1}", key, _cachedValues[key]));
return _cachedValues[key];
})
.Result;
outError = error;
return result;
}
Debug.WriteLine(string.Format("Returning cached {0}: {1}", key, _cachedValues[key]));
return _cachedValues[key];
}
catch (WebException)
{
return null;
}
}