System.Drawing в службах Windows или ASP.NET - PullRequest
16 голосов
/ 24 декабря 2008

Согласно MSDN , не очень хорошая идея использовать классы в пространстве имен System.Drawing в службе Windows или службе ASP.NET. Сейчас я занимаюсь разработкой библиотеки классов, которой может потребоваться доступ к этому конкретному пространству имен (для измерения шрифтов), но нельзя гарантировать, что хост-процесс не является службой.

Теперь есть менее оптимальный метод, к которому я могу обратиться, если System.Drawing недоступен, но если это возможно, я бы предпочел использовать классы в System.Drawing. Итак, что я хотел бы сделать, это определить в runtume, безопасен ли System.Drawing, и, если это так, использовать его, в противном случае перейдите к неоптимальному варианту.

Моя проблема: Как я могу определить, безопасно ли использовать System.Drawing?

Я думаю, мне следует либо

  • Определить, является ли текущий процесс службой Windows или ASP.NET
  • Определить, доступен ли GDI
  • Или, может быть, есть способ спросить саму System.Drawing.dll, безопасно ли использовать

К сожалению, я не могу придумать способ реализовать любой из этих подходов. У кого-нибудь есть идеи?

Ответы [ 5 ]

18 голосов
/ 24 декабря 2008

Чтобы устранить путаницу, System.Drawing работает в ASP.NET и службах, просто не поддерживается . Могут возникнуть проблемы с высокой нагрузкой (из-за неуправляемых ресурсов), утечками памяти или ресурсов (плохо реализованными или вызванными шаблонами утилизации) и / или появлением диалоговых окон, когда нет рабочего стола, на котором они отображаются.

Тестирование позаботится о последнем, а мониторинг предупредит вас о первом. Но, если / когда у вас возникнут проблемы, не ожидайте, что сможете позвонить в PSS и попросить исправить ситуацию.

Итак, какие у вас варианты? Что ж, если вам не нужен полностью поддерживаемый маршрут, и вы не ожидаете экстремальной нагрузки - многие люди проигнорировали предупреждение MSDN и успешно использовали System.Drawing. Некоторые из них были укушены, но успеха гораздо больше, чем историй неудач.

Если вы хотите что-то поддерживать, вам нужно знать, работает ли он в интерактивном режиме или нет. Лично я, вероятно, просто оставлю это на усмотрение хостинг-приложения, чтобы установить неинтерактивный флаг где-либо. В конце концов, приложение находится в лучшем положении, чтобы определить, находятся ли они в размещенной среде и / или хотят рисковать проблемами GDI +.

Но, если вы хотите автоматически определять вашу среду, я полагаю, что есть худшие ответы, чем предлагаются здесь, на SO для службы. Подводя итог, вы можете либо проверить EntryAssembly, чтобы увидеть, если он наследует от ServiceBase, либо попытаться получить доступ к System.Console. Для ASP.NET, в том же духе, достаточно обнаружения HttpContext.Current.

Я бы подумал был бы управляемый или p / invoke способ поиска рабочего стола (который, я думаю, действительно является определяющим фактором во всем этом) и / или что-то вне AppDomain который подскажет вам. Но я не уверен, что это такое, и MSDN не слишком хорошо освещает это.

Редактировать: Троллинг MSDN, я вспомнил, что это на самом деле Window Station (которая содержит рабочий стол), это важный бит здесь. С помощью этой информации я смог найти GetProcessWindowStation () , который возвращает дескриптор текущей оконной станции. Передав этот дескриптор GetUserObjectInformation () , вы получите структуру USEROBJECTFLAGS с dwFlags с WSF_VISIBLE, если у вас есть видимый рабочий стол.

В качестве альтернативы, EnumWindowsStations предоставит вам список станций, которые вы можете проверить - WinSta0 является интерактивной.

Но, да, я все еще думаю, что просто установить в приложении свойство или что-то еще - это намного более простой маршрут ....

Снова отредактируйте: через 7 лет я узнаю о Environment.UserInteractive , где MS исполняет танец GetProcessWindowStation , который я описал выше для вас ... Я все равно рекомендую делегирование хост-приложению (оно может хотеть более быстрого, но немного более рискованного пути System.Drawing), но UserInteractive, по-видимому, является хорошим вариантом по умолчанию, если его не вводить самостоятельно.

4 голосов
/ 18 июня 2010

Несмотря на то, что это официально не поддерживается, я годами широко использовал классы System.Drawing на большом веб-сервере (как веб-приложения, так и веб-сервисы) без каких-либо проблем с производительностью или надежностью.

Я думаю, что единственный способ определить, является ли код безопасным для использования, - это тестировать, отслеживать и переносить любой объект с внешними ресурсами с помощью операторов {}.

1 голос
/ 24 декабря 2008

Вместо этого вы можете использовать TextRenderer . Я знаю, что странно использовать что-то из System.Windows.Forms в ASP.NET, но похоже, что оно не имеет того же предупреждения о том, что не поддерживается в ASP.NET. Я использовал и TextRenderer, и Graphics.MeasureString для измерения строк в приложениях ASP.NET, поэтому они оба работают. Я никогда не видел предупреждение о том, что System.Drawing не рекомендуется в ASP.NET.

TextRenderer намного медленнее, чем Graphics.MeasureString, FWIW.

0 голосов
/ 24 декабря 2008

Возможно, это связано с подсистемой GDI, которой необходим поток STA. Если это так, исследуйте указание ASPCOMPAT = TRUE в вашей директиве @PAGE для соответствующей страницы aspx. Это запустит страницу aspx в потоке STA, IIRC.

-Oisin

0 голосов
/ 24 декабря 2008

Возможно, вы сможете скопировать System.Drawing.dll в корзину вашего приложения и затем использовать его таким образом. Это может гарантировать его доступность.

Просто щелкните правой кнопкой мыши ссылку в вашем приложении и измените параметр для Копировать локальный на true .

Возможно, я неправильно понимаю вопрос ...

...