2013-05-15 3 views
2

나는 Bureau 또는 Meteorology에서 7 일간의 예측 데이터를 수집하고이를 웹 페이지에 표시하는 수업을 가지고 있습니다. 30 분마다 스크립트가 실행되어 국에서 업데이트 된 데이터를 가져옵니다.주어진 키가 사전에 없습니다. dictionary.ContainsKey ("given_key") == true

국은 머리글 행이있는 탭 구분 형식으로 데이터를 제공합니다. 모든 필드를 추출한 후 값을 구문 분석을 위해 Dictionary<string,string>에 넣습니다. 분명한 이유로 데이터 구성을위한 중요한 필드는 "forecast_date"입니다. 따라서 구문 분석을 시작하기 전에 사전에 실제로이 키가 포함되어 있는지 확인합니다. 이것은 실제로 대부분의 작동

static object ForecastLockingObj= new object(); 
private void UpdateWeather() 
{ 
    if(isTimeForUpdate()) 
    { 
     lock(ForecastLockingObj) 
     { 
      if(isTimeForUpdate()) 
      { 
       Dictionary<string, string> ForecastData = Get7DayForecast(); 
       int forecastDate = int.MinValue; 
       if (ForecastData.ContainsKey("forecast_date") && int.TryParse(ForecastData["forecast_date"], out forecastDate)) 
       { 
        //Parse the data 
        SetNextUpdateTime(); 
       } 
      } 
     } 
    } 
} 

:

는 여기에 내가 뭘하는지 매우 간단한 예입니다. 그러나 아주 가끔 나는 다음과 같은 예외를 얻을 수 있습니다 :

라인 (231) 다음 "forecast_date"의 존재를 확인하는 정수로 구문 분석을 시도하는 경우 문이
[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 

. 노트; 이 서비스는 날짜를 정수 (예 : 20130515)로 안정적으로 렌더링하므로 온 전성 검사에 가깝습니다.

ContainsKey이 예외를 던져서는 안되므로 내 TryParse에서 ForecastData["forecast_date"]을 참조해야한다고 생각합니다.

내 질문은 이것입니다. ContainsKey가 false를 반환하면 TryParse가 실행되지 않아야합니다. 그렇다면 왜 한 문장에서 키의 존재를보고하고 다음 문장에서 그 존재를 부인할 것입니다 ... 우리가 자물쇠 안에 있고 우리가 작업하고있는 사전은 비 정적이고 지역적입니다.

제쳐두고; 이것은 일반적으로 국장이 다음 장거리 예측을 발표 할 때 오후에 발생합니다. 예외는 몇 페이지의로드에 대해 발생하고 권한 자체에 대해 발생합니다. 여기


는 코드가 실패하지만 당신이 무엇을보고 Trace을 활용 고려해야하는 이유

private Dictionary<string, string> Get7DayForecast() 
{ 
    int linenumber = 0; 
    int locationNameKey = 0; 
    List<string> keys = new List<string>(); 
    Dictionary<string, string> myLocationData = new Dictionary<string, string>(); 

    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") && ftp_response.StatusDescription.StartsWith("150")) 
    { 
     Stream ftp_responseStream = ftp_response.GetResponseStream(); 
     StreamReader ftp_reader = new StreamReader(ftp_responseStream); 

     while (ftp_reader.Peek() >= 0) 
     { 
      linenumber++; 
      string line = ftp_reader.ReadLine(); 
      List<string> temp = (List<string>)line.Split(ForecastDelimiter).ToList<string>(); 
      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 && temp[locationNameKey] == ForecastLocationName) 
      { 
       for (int i = 0; i < 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; 
} 
+0

사전이 잠금 장치 내에서 정의되는 것이 중요합니까? 자물쇠 안에 정의 된 것은 쓰레드에 안전하다는 것을 알았습니다. –

+1

'lock' 문에 의해 다중 스레드를 사용하고 있다고 가정합니다. 'Get7DayForecast'가 반환 한 동일한 객체에서 itens를 제외하는 다른 메소드는 없습니까? – fhelwanger

+0

흠 ... 아니'Get7DayForecast'는'lock' 문 안에서'UpdateWeather'에 의해서만 사용됩니다. 또한 크게 캡슐화되어 있습니다. 서비스의 FTP 주소 (예 ... FTP)와 데이터를 가져 오려는 City의 코드를 제외하고 모든 객체는 메소드에 정의되어 있습니다. –

답변

2

솔직히 내가 볼 수없는 전체 Get7DayForecast 방법을이다. 또한 대신 TryGetValue을 사용해서는 안됩니다.

var map = Get7DayForecast(); 

string forecastDateString; 
if (!map.TryGetValue("forecast_date", out forecastDateString)) 
{ 
    Trace.WriteLine("forecast_date entry was not found."); 
    return; 
} 

int foreCastDate; 
if (!int.TryParse(forecastDateString, out foreCastDate) 
{ 
    Trace.WriteLine("Value was not a valid integer: " + forecastDateString); 
    return; 
} 

SetNextUpdateTime(); 
관련 문제