Бөлісу құралы:


Внутрипроцессное параллельное выполнение

Примечание.

Эта статья относится к .NET Framework. Он не применяется к более новым реализациям .NET, включая .NET 6 и более поздние версии.

Начиная с .NET Framework 4, разработчики могут использовать внутрипроцессное параллельное размещение для запуска нескольких версий среды CLR в одном процессе. Управляемые COM-компоненты по умолчанию выполняются в той версии платформы .NET Framework, в которой они были созданы, вне зависимости от загруженной для процесса версии .NET Framework.

Общие сведения

Платформа .NET Framework всегда предоставляла возможность параллельного размещения для приложений с управляемым кодом, но до появления версии .NET Framework 4 эта функция не была доступна для управляемых COM-компонентов. Загруженные в процесс COM-компоненты в прошлом выполнялись в уже загруженной версии среды выполнения или в последней установленной версии платформы .NET Framework. Если эта версия была несовместима с COM-компонентом, то выполнение завершалось ошибкой.

Платформа .NET Framework 4 предоставляет новый подход к параллельному размещению, который обеспечивает выполнение следующих требований:

  • Установка новой версии платформы .NET Framework не повлияет на существующие приложения.

  • Приложения будут выполняться в той версии платформы .NET Framework, в которой они были построены. Новая версия платформы .NET Framework не используется, если явным образом не указано иное. В то же время приложения легче перевести на использование новой версии платформы .NET Framework.

Влияние на пользователей и разработчиков

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

  • Разработчики приложений. Параллельное размещение не затрагивает разработчиков приложений. Приложения по умолчанию всегда выполняются в версиях платформы .NET Framework, в которых они были созданы. Это поведение не изменено. Разработчики могут переопределить это поведение и настроить приложение на выполнение в более новой версии платформы .NET Framework (см. сценарий 2).

  • Разработчики и пользователи библиотек. Параллельное размещение не устраняет проблемы совместимости, с которыми сталкиваются разработчики библиотек. Библиотека, загруженная приложением напрямую (через прямую ссылку или с помощью вызова Assembly.Load) продолжает использовать среду выполнения класса AppDomain, в который она загружена. Следует проверить корректность работы библиотек со всеми версиями платформы .NET Framework, поддержка которых необходима. Если приложение компилируется с помощью среды выполнения .NET Framework 4, но содержит библиотеку, построенную с помощью более старой среды выполнения, эта библиотека также будет использовать среду выполнения .NET Framework 4. Но, если приложение было создано с помощью более старой среды выполнения и библиотеки, которая построена в .NET Framework 4, приложение также необходимо явным образом настроить на использование .NET Framework 4 (см. сценарий 3).

  • Разработчики управляемых COM-компонентов. Управляемые COM-компоненты ранее автоматически выполнялись в последней версии среды выполнения, установленной на компьютере. Теперь COM-компоненты можно запускать в той версии среды выполнения, в которой они были созданы.

    Как отражено в следующей таблице, созданные на платформе .NET Framework версии 1.1 компоненты могут запускаться параллельно с компонентами версии 4, но не могут выполняться вместе с компонентами версий 2.0, 3.0 или 3.5, так как параллельное размещение для этих версий невозможно.

    Версия платформы .NET Framework 1,1 2.0 - 3.5 4
    1,1 Нет данных No Да
    2.0 - 3.5 No Нет данных Да
    4 Да Да Неприменимо

Примечание.

Версии платформы .NET Framework 3.0 и 3.5 созданы с помощью инкрементального построения на базе версии 2.0 и не требуют параллельного запуска. По сути они представляют собой одну и ту же версию.

Общие сценарии параллельного размещения

  • Сценарий 1. Собственное приложение, которое использует COM-компоненты, созданные в более ранних версиях платформы .NET Framework.

    платформа .NET Framework версии, установленные: платформа .NET Framework 4 и все остальные версии платформа .NET Framework, используемые com-компонентами.

    Необходимые действия: в этой ситуации не следует предпринимать никаких действий. COM-компоненты будут выполняться в той версии платформы .NET Framework, в которой они были зарегистрированы.

  • Сценарий 2. Управляемое приложение, созданное с помощью платформа .NET Framework 2.0 с пакетом обновления 1 (SP1), которое вы предпочитаете запускать с платформа .NET Framework 2.0, но готовы работать на платформа .NET Framework 4, если версия 2.0 отсутствует.

    платформа .NET Framework версии, установленные: более ранняя версия платформа .NET Framework и платформа .NET Framework 4.

    Что делать: в файле конфигурации приложения в каталоге приложения используйте <элемент запуска> и поддерживаемый< набор элементовRuntime> следующим образом:

    <configuration>
      <startup >
        <supportedRuntime version="v2.0.50727" />
        <supportedRuntime version="v4.0" />
      </startup>
    </configuration>
    
  • Сценарий 3. Собственное приложение, использующее com-компоненты, созданные с более ранними версиями платформа .NET Framework, которые требуется запустить с помощью платформа .NET Framework 4.

    платформа .NET Framework версии, установленные: платформа .NET Framework 4.

    Необходимые действия: откройте файл конфигурации приложения в каталоге приложения и используйте элемент <startup>, атрибут useLegacyV2RuntimeActivationPolicy которого имеет значение true, и набор элементов <supportedRuntime> следующим образом:

    <configuration>
      <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0" />
      </startup>
    </configuration>
    

Пример

В следующем примере показан неуправляемый узел COM, в котором управляемый COM-компонент выполняется с помощью версии платформы .NET Framework, для которой был предназначен данный компонент.

Чтобы выполнить следующий пример, скомпилируйте и зарегистрируйте следующий управляемый COM-компонент с помощью платформа .NET Framework 3.5. Чтобы зарегистрировать компонент, в меню Проект выберите пункт Свойства, перейдите на вкладку Сборка, а затем установите флажок Регистрация для COM-взаимодействия.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace BasicComObject
{
    [ComVisible(true), Guid("9C99C4B5-CA54-4c58-8988-49B6811BA53B")]
    public class MyObject : SimpleObjectModel.IPrintInfo
    {
        public MyObject()
        {
        }
        public void PrintInfo()
        {
            Console.WriteLine("MyObject was activated in {0} runtime in:\n\tAppDomain {1}:{2}", System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion(), AppDomain.CurrentDomain.Id, AppDomain.CurrentDomain.FriendlyName);
        }
    }
}

Скомпилируйте следующее неуправляемое приложение C++, которое активирует COM-объект, созданный в предыдущем примере.

#include "stdafx.h"
#include <string>
#include <iostream>
#include <objbase.h>
#include <string.h>
#include <process.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    char input;
    CoInitialize(NULL) ;
    CLSID clsid;
    HRESULT hr;
    HRESULT clsidhr = CLSIDFromString(L"{9C99C4B5-CA54-4c58-8988-49B6811BA53B}",&clsid);
    hr = -1;
    if (FAILED(clsidhr))
    {
        printf("Failed to construct CLSID from String\n");
    }
    UUID id = __uuidof(IUnknown);
    IUnknown * pUnk = NULL;
    hr = ::CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,id,(void **) &pUnk);
    if (FAILED(hr))
    {
        printf("Failed CoCreateInstance\n");
    }else
    {
        pUnk->AddRef();
        printf("Succeeded\n");
    }

    DISPID dispid;
    IDispatch* pPrintInfo;
    pUnk->QueryInterface(IID_IDispatch, (void**)&pPrintInfo);
    OLECHAR FAR* szMethod[1];
    szMethod[0]=OLESTR("PrintInfo");
    hr = pPrintInfo->GetIDsOfNames(IID_NULL,szMethod, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
    DISPPARAMS dispparams;
    dispparams.cNamedArgs = 0;
    dispparams.cArgs = 0;
    VARIANTARG* pvarg = NULL;
    EXCEPINFO * pexcepinfo = NULL;
    WORD wFlags = DISPATCH_METHOD ;
;
    LPVARIANT pvRet = NULL;
    UINT * pnArgErr = NULL;
    hr = pPrintInfo->Invoke(dispid,IID_NULL, LOCALE_USER_DEFAULT, wFlags,
        &dispparams, pvRet, pexcepinfo, pnArgErr);
    printf("Press Enter to exit");
    scanf_s("%c",&input);
    CoUninitialize();
    return 0;
}

См. также