Ориентация x86 против AnyCPU при построении для 64-битных оконных ОС

У меня есть существующее приложение С#, написанное для .NET 2.0, и таргетинг на AnyCPU на данный момент. В настоящее время он ссылается на некоторые сторонние .NET-библиотеки DLL, для которых у меня нет источника (и я не уверен, были ли они созданы для x86, x64 или AnyCPU).

Если я хочу запустить свое приложение специально на 64-битной ОС Windows, какой платформе я должен настроить таргетинг, чтобы мое приложение запускалось без ошибок? Мое понимание на данный момент нацелено:

  • x86. Если по крайней мере одна сторонняя .NET-библиотека DLL построена для x86 или использует p/Invoke для взаимодействия с DLL файлами Win32. Приложение будет работать в 32-битном режиме на 32-битных и 64-битных операционных системах.
  • x64. Если все сторонние DLL файлы сторонних разработчиков уже созданы для x64 или AnyCPU. Приложение будет работать только в 64-битных операционных системах.
  • AnyCPU: если все сторонние .NET-библиотеки DLL уже созданы для AnyCPU. Приложение будет работать в 32-битном режиме на 32-битных операционных системах и 64-битных в 64-битных операционных системах.

Кроме того, могу ли я поверить в то, что в то время как таргетинг AnyCPU не будет генерировать ошибок при создании приложения, ссылающегося на сторонние x86.NET DLL, приложение будет бросать исключение во время выполнения, когда пытается загрузить эти DLL, когда оно работает на 64 разрядной ОС.

Следовательно, если одна из моих сторонних DLL файлов выполняет p/Invoke или x86, я могу использовать только x86 для этого приложения?

Ответ 1

Вы можете делать P/Invoke из DLL AnyCPU, вам просто нужно быть немного более осторожным в определениях P/Invoke (т.е. вы случайно не предполагаете 32-битное или что-то еще). Проблема в том, что трудно понять, делает ли третья сторона DLL правильной вещью без Reflector и разбирает ее (если разработчик не заявляет, конечно, 64-битную поддержку, конечно).

Но кроме этого вы довольно много спотыкаетесь.

Честно говоря, для 99% приложений цель x86 вполне приемлема. Это относительно небольшое количество приложений, которые на самом деле выигрывают от 64-битного. (Проблемы с производительностью обычно выходят из-за стирки: больше регистров компенсируется переименованием регистров в режиме x86 и более крупными структурами данных, поскольку указатели в два раза больше [и в такой тяжелой системе, как .NET, что еще хуже])

Ответ 2

Мне было любопытно относиться к этой конкретной части вашего вопроса.

Кроме того, могу ли я поверить, что пока для цели AnyCPU не будет ошибки при создании приложения ссылаясь на сторонние x86.NET DLL, приложение будет вызывать время выполнения исключение, когда он пытается загрузить эти DLL при работе на 64-разрядной ОС.

Итак, я попробовал. Я создал проект DLL ClassLibrary1, который нацелился на x86, а затем добавил ConsoleApplication1, который нацелился на AnyCPU и ссылался на другой проект. Я действительно использовал класс из проекта ClassLibrary1 в методе Main.

Visual Studio не давала мне никаких предупреждений или жалоб о ссылках или создании приложения. Когда я запустил приложение (в 64-разрядной ОС) и сборка ClassLibrary1 была загружена, меня встретили исключение BadImageFormatException.

Если я изменил ConsoleApplication1 на целевой x64, я получаю предупреждения компилятора, но компиляция завершается успешно, и во время выполнения происходит такое же исключение.

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