2014-11-18 6 views
9

В нашем приложении .NET 4.0 Winforms некоторые пользователи (все Win7 x64) недавно испытали очень долгое время ожидания (по сравнению с другими), когда приложение сохраняет свои настройки с помощью этого кода:Сохранение пользовательских настроек .NET занимает очень много времени

Properties.Settings.Default.Save(); 
  • Типичные длительности: от 0,5 до 1 секунды
  • Экстремальные длительностей: от 15 до 20 секунд

приложений настройки (объем: Пользователь, все сохраняется в User.config под AppData \ Local \\) состоит из нескольких пользовательских классов, а также два класса, представляющих параметры принтера: System.Drawing.Printing.PageSettings и System.Drawing.Printing.PrinterSettings

Использования GlowCode профилировщик на одном из этих машин, я нашел следующую функцию, чтобы принять 17 секунд:

<Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPrinterSettings_x003A__x003A_Write9_PrinterSettings Nodes="1" Visits="1" percent_in_Child="100.00 %" Time_in_Child="17.456" Time="17.456" Avg._Time_in_Child_="17.456" Avg._Time="17.456" Blocks_net="12" Bytes_net="1024" Blocks_gross="1087" Bytes_gross="494146" /> 

, продолжительность была почти поровну на три геттеров (взятых из зрителя GlowCode):

  • PrinterSettings :: get_PaperSizes
  • PrinterSettings :: get_PaperSources
  • PrinterSettings :: get_PrinterResolutions

Doing некоторые исследования показали следующие страницы: https://social.msdn.microsoft.com/Forums/vstudio/en-US/8fd2132a-63e8-498e-ab27-d95cdb45ba87/printersettings-are-very-slow и http://www.pcreview.co.uk/forums/papersources-and-papersizes-really-slow-some-systems-t3660593.html, цитата:

В некоторых системах , особенно Vista x64, требуется навсегда (от 5 до 15 секунд, если скомпилировано за x64, 10-20 секунд, если скомпилированный для x86), чтобы перечислить либо в документе, либо в виде документов, которые собирают объект printersettings.

С помощью небольшого тестового приложения просто экономия PrinterSettings показал экономию времени около 3,5 секунд на одном из этих «медленных» машин, в то время как другой был совсем не впечатлен длительностью 0,2 секунды, что соответствует моей быстрой машине развития ,

Любые идеи о причинах и о том, как улучшить это?

Как я могу найти реальные причины этих задержек?

Редактировать: Спасибо, что указали, что настройки принтера получены через драйвер, это может объяснить задержки на определенных машинах.

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

Кроме того, я не буду (я знаю, я знаю) уменьшить информацию PrinterSettings быть сохранены только потому, что некоторые люди могут испытывать задержку и разорвать обратную совместимость в конце концов ...

Может быть, если я пытаюсь сериализации в фоновом режиме (после того, как пользователь выполнил некоторые изменения в принтере?) Это может ускорить вещи ...

+1

Я подозреваю, что PrinterSettings объект должен повторный запрос принтера для его информации, и что это медленно. Почему вы должны сохранить объект PrinterSettings?Данные, полученные от него, могут измениться, если физический принтер изменится. Вероятно, лучше не кэшировать эту информацию. –

+1

Во-первых, Добро пожаловать в переполнение стека! Во-вторых, +1 для очень хорошо написанного первого вопроса! Вы ясно сделали много исследований в этом уже ** И ** задокументировали это. –

+0

У меня есть проект, который делает то же самое, по большей части, и без проблем. В машине, ведущей на работу сейчас, я могу выкопать ее и опубликовать ее позже этим утром. Тем не менее, в vb. Если я правильно помню, это связано с использованием пользовательской оболочки, которая сериализовала каждый бит по-разному. – pinkfloydx33

ответ

1

Первое предложение:

Призывы для извлечения источников бумаги и размера бумаги в настоящее время передаются через водителя. Лучше всего убедиться, что установлена ​​самая новая версия драйвера. Возможно, что старые версии драйвера (в частности, те, что были на компакт-диске, которые были в коробке) являются старыми и ошибочными. Если вы еще этого не сделали, нажмите на сайт производителя и возьмите последнюю версию.

Второе предложение

Кроме того, он собирается быть боль, но вы можете попробовать использовать основные Win32 API, а не коллегами CLR. В этом случае вы должны позвонить GetPrinter, запросив структуру PRINTER_INFO_2. После этого вы можете проверить pDevMode, чтобы получить структуру DEVMODE, в которой есть вся информация, которую вы ищете.

This question или this question должно быть полезно.

Вместо сохранения всего экземпляра класса PrinterSettings сохраняются только индивидуальные настройки в качестве базовых типов. Держите его простым: строки, ints, bools и т. Д. Очевидно, что Serializer запрашивает связь с принтером, и это то, что вводит задержку. Я готов поспорить, что если вы возьмете отдельных членов класса и сериализуете их самостоятельно, вы увидите улучшение.

Очевидно, это означает, что при загрузке параметров вам необходимо десериализовать все эти параметры в новый класс PrinterSettings и применить их.

EDIT 1, в ответ на вопрос редактировать

Это правда - вы могли бы асинхр Save() работать в фоновом режиме. Ваша единственная проблема будет, если пользователь попытается завершить процесс (закрыть приложение) до завершения сохранения. Вам нужно будет поддерживать bool относительно того, происходит ли сохранение (установлено значение false при срабатывании обратного вызова). Если пользователь пытается выйти из приложения, а bool - true, поставьте «Подождите, пока настройки будут сохранены ...», пока bool не станет ложным.

+0

После того, как я перечитаю ваш вопрос, теперь я сомневаюсь, что последняя часть моего ответа будет полезна вообще. Не похоже, что вы контролируете код, вызывающий запрос параметров принтера. Мое предложение обновить драйверы по-прежнему стоит. –

+0

Отредактировал мой ответ с более подходящим предложением. –

+0

Вы можете просто использовать поток переднего плана ([Thread.IsBackground = false] (http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground (v = vs.110) .aspx)) и всегда показывать сообщение «Подождите, пока вы выключите». Таким образом, вам не нужно сообщать состояние потока. –

0

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

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

Во время остановки (форма близко), эти параметры являются не назначены еще раз, но мы по-прежнему сохранить все (используя Properties.Settings.Default.Save()) и как-то сериализатор признает, что у них нет изменений для запроса и поэтому экономия заканчивается очень быстро:

Между 0,02 и 0,05 секунды, но все настройки сохраняются правильно!

Интересный факт: этот вопрос был первым сообщили в неделе, когда мы получили новый офисный принтер :)

Смежные вопросы