Использование большого статического массива в С# (Silverlight на Windows Phone 7)

У меня есть вопрос, который так просто, я не могу поверить, что не могу ответить сам. Но, вы идете.

У меня есть большой статический список (из городов, широт и долгот), который я хочу использовать в моем приложении Windows Phone 7 Silverlight. Их насчитывается около 10 000 человек. Я хотел бы встроить эти данные статически в мое приложение и получить доступ к нему в массиве (мне нужно регулярно перебирать весь список в коде).

Что будет моим самым эффективным способом хранения этого? Я немного похожа на старую школу, поэтому я посчитал, что это самый быстрый способ сделать это:

public struct City
{
    public string name;
    public double lat;
    public double lon;
};

а затем...

private City[] cc = new City[10000];

public CityDists()
{
    cc[2].name = "Lae, Papua New Guinea"; cc[2].lat = 123; cc[2].lon = 123;
    cc[3].name = "Rabaul, Papua New Guinea"; cc[3].lat = 123; cc[3].lon = 123;
    cc[4].name = "Angmagssalik, Greenland"; cc[4].lat = 123; cc[4].lon = 123;
    cc[5].name = "Angissoq, Greenland"; cc[5].lat = 123; cc[5].lon = 123;
...

Тем не менее, это завершается ошибкой "из памяти", прежде чем код действительно начнет работать (я предполагаю, что сам код оказался слишком большим для загрузки в память).

Все, что я читаю в сети, говорит мне использовать XML-ресурс или файл, а затем десериализовать это в экземплярах класса. Но может ли это быть так же быстро, как использование структуры? Разве XML не займет время для разбора?

Я думаю, что могу писать код здесь - я просто не уверен, с чего лучше всего начать. Меня интересует скорость загрузки и (что еще более важно) доступ к времени выполнения больше всего.

Любая помощь очень ценится - первый вопрос здесь, поэтому я надеюсь, что я ничего не сделал.

Крис

Ответ 1

Если загрузка xml-документа из xap работает для вас.

Здесь проект, который я опубликовал, демонстрирует загрузку XML-документа из XAP через XDocument/LINQ и привязку данных к списку для ссылки.

привязка источника данных Linq к списку

Ответ 2

У 10 000 структур не должно хватить памяти, но чтобы убедиться, что я сначала попытаюсь превратить вашу структуру в класс, чтобы она использовала кучу вместо стека. Существует большая вероятность того, что это исправит ошибки вашей памяти.

Файл XML, хранящийся в изолированном хранилище, может быть хорошим способом, если ваши данные будут обновляться даже каждый раз в то время. Вы можете вытащить города из веб-службы и сериализовать эти классы в хранилище приложений в изолированном хранилище, когда они обновляются.

Кроме того, в примерах кода я замечаю, что массив cc не объявлен статическим. Если у вас есть несколько экземпляров CityDists, то это также может привести к увязке с памятью, так как массив получает повторное создание каждый раз, когда создается новый класс CityDists. Попробуйте объявить массив как статический и инициализировать его в статическом конструкторе:

private static City[] cc = new City[10000];

static CityDists()
{
    cc[2].name = "Lae, Papua New Guinea"; cc[2].lat = 123; cc[2].lon = 123;
    cc[3].name = "Rabaul, Papua New Guinea"; cc[3].lat = 123; cc[3].lon = 123;
    cc[4].name = "Angmagssalik, Greenland"; cc[4].lat = 123; cc[4].lon = 123;
    cc[5].name = "Angissoq, Greenland"; cc[5].lat = 123; cc[5].lon = 123;
...

Ответ 3

Если вы хотите избежать синтаксического анализа XML и служебных данных памяти, вы можете использовать простой текстовый файл для хранения ваших данных и использовать функции токенизатора .Net для синтаксического анализа записей, например. используйте String.Split()

Вы также можете частично загрузить файл, чтобы снизить потребление памяти. Например, вы загружаете только k из n строк файла. Если вам нужно получить доступ к записи, находящейся за пределами загруженных k сегментов, загрузите соответствующие k сегментов. Вы можете либо сделать это по старой школе, либо даже использовать причудливые материалы для сериализации из .Net

Ответ 4

Использование такого файла, как XML или простой разделительный файл, будет лучшим подходом, как указывали другие. Однако я могу предложить еще одно изменение для улучшения использования памяти.

Что-то вроде этого (хотя фактическая загрузка должна выполняться с использованием внешнего файла): -

public struct City 
{ 
    public string name;
    public string country; 
    public double lat; 
    public double lon; 
}

private static City[] cc = new City[10000];
static CityDists()  
{
    string[] countries = new string[500];
    // Replace following with loading from a "countries" file.
    countries[0] = "Papua New Guinea";
    countries[1] = "Greenland";

    // Replace following with loading from a "cities" file.
    cc[2].name = "Lae"; cc[2].country = contries[0]; cc[2].lat = 123; cc[2].lon = 123; 
    cc[3].name = "Rabaul"; cc[3].country = countries[0]; cc[3].lat = 123; cc[3].lon = 123;             
    cc[4].name = "Angmagssalik"; cc[4].country = countries[1]; cc[4].lat = 123; cc[4].lon = 123;             
    cc[5].name = "Angissoq"; cc[5].country= countries[1]; cc[5].lat = 123; cc[5].lon = 123;             
 }

Это немного увеличивает размер структуры, но значительно уменьшает память, используемую для дублирования названий стран.

Ответ 5

Я слышал ваше разочарование. Запустите свой код без отладчика, он должен работать нормально. Я загружаю 2 массива менее чем за 3 секунды, каждый из которых содержит более 100 000 элементов. Отладчик сообщает "Out of Memory", что просто не так.

О, и вы правы в эффективности. Загрузка одной и той же информации из файла XML занимала более 30 секунд на телефоне.

Я не знаю, кто отвечал на ваш вопрос, но они действительно должны придерживаться маркетинга.