Note that there are some explanatory texts on larger screens.

plurals
  1. POThe given key was not present in the dictionary. Even when dictionary.ContainsKey("given_key") == true
    primarykey
    data
    text
    <p>I have a class that gathers 7-day forecast data from the Bureau or Meteorology and presents it on a web page. A script runs every 30 minutes to get updated data from the Bureau.</p> <p>The bureau provides data in a tab delimited format with a header row. After extracting all the fields, I put the values into a <code>Dictionary&lt;string,string&gt;</code> for parsing. For obvious reasons, the important field for organising the data is the "forecast_date". So before I begin parsing, I make sure that my dictionary actually contains this key.</p> <p>Here is a very simplified example of what I'm doing:</p> <pre><code>static object ForecastLockingObj= new object(); private void UpdateWeather() { if(isTimeForUpdate()) { lock(ForecastLockingObj) { if(isTimeForUpdate()) { Dictionary&lt;string, string&gt; ForecastData = Get7DayForecast(); int forecastDate = int.MinValue; if (ForecastData.ContainsKey("forecast_date") &amp;&amp; int.TryParse(ForecastData["forecast_date"], out forecastDate)) { //Parse the data SetNextUpdateTime(); } } } } } </code></pre> <p>This actually works for the most part. But very occasionally I'll get the following exception:</p> <pre><code>[KeyNotFoundException: The given key was not present in the dictionary.] System.ThrowHelper.ThrowKeyNotFoundException() +28 System.Collections.Generic.Dictionary`2.get_Item(TKey key) +7457036 CoA.WebUI.Controls.WeatherWidget.UpdateWeather() in C:\dev\WeatherWidget.cs:231 </code></pre> <p>Where line 231 is the if statement that checks the existence of "forecast_date" then attempts to parse it into an integer. Note; the service reliably renders dates as integers (e.g. 20130515) and so this is more of a sanity check.</p> <p><code>ContainsKey</code> should not be throwing this exception, so I feel it must be where I refer to <code>ForecastData["forecast_date"]</code> in my TryParse. </p> <p>My question is this; surely if ContainsKey returns false, then TryParse should not run. So why would it report the existence of a key in one statement and then deny its existence in the very next statement... whilst we are inside a lock and the Dictionary we're working on is non-static and local?</p> <p>As an aside; this typically happens in the afternoon, when the Bureau releases the next long range forecast. The exception happens for a few page-loads and then rights itself.</p> <hr> <p>Here is the full Get7DayForecast method</p> <pre><code>private Dictionary&lt;string, string&gt; Get7DayForecast() { int linenumber = 0; int locationNameKey = 0; List&lt;string&gt; keys = new List&lt;string&gt;(); Dictionary&lt;string, string&gt; myLocationData = new Dictionary&lt;string, string&gt;(); FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(ForecastURL); ftp.Method = WebRequestMethods.Ftp.DownloadFile; ftp.Credentials = new NetworkCredential(); FtpWebResponse ftp_response = (FtpWebResponse)ftp.GetResponse(); if (ftp_response.WelcomeMessage.StartsWith("230") &amp;&amp; ftp_response.StatusDescription.StartsWith("150")) { Stream ftp_responseStream = ftp_response.GetResponseStream(); StreamReader ftp_reader = new StreamReader(ftp_responseStream); while (ftp_reader.Peek() &gt;= 0) { linenumber++; string line = ftp_reader.ReadLine(); List&lt;string&gt; temp = (List&lt;string&gt;)line.Split(ForecastDelimiter).ToList&lt;string&gt;(); if (linenumber == 1) { //Break if the header line does not contain the fields we require if (!ForecastRequiredFields.All(line.Contains)) { break; } keys = temp; locationNameKey = keys.IndexOf(ForecastLocationFieldName); } else if (temp.Count == keys.Count &amp;&amp; temp[locationNameKey] == ForecastLocationName) { for (int i = 0; i &lt; keys.Count; i++) { myLocationData.Add(keys[i], temp[i]); } //Break if we've just parsed the data we were looking for break; } } ftp_reader.Close(); } ftp_response.Close(); return myLocationData; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload