Wykonywanie równoczesne i wewnątrzprocesowe

Począwszy od programu .NET Framework 4, możesz użyć hostingu równoległego równoległego do uruchamiania wielu wersji środowiska uruchomieniowego języka wspólnego (CLR) w jednym procesie. Domyślnie zarządzane składniki COM są uruchamiane z wersją programu .NET Framework, z którą zostały skompilowane, niezależnie od wersji programu .NET Framework załadowanej do procesu.

Tło

Program .NET Framework zawsze zapewniał hosting równoległy dla aplikacji kodu zarządzanego, ale przed programem .NET Framework 4 nie zapewniał tej funkcji dla zarządzanych składników COM. W przeszłości zarządzane składniki COM, które zostały załadowane do procesu, były uruchamiane z wersją środowiska uruchomieniowego, która została już załadowana lub z najnowszą zainstalowaną wersją programu .NET Framework. Jeśli ta wersja nie jest zgodna ze składnikiem COM, składnik zakończy się niepowodzeniem.

Program .NET Framework 4 zapewnia nowe podejście do hostingu równoległego, które zapewnia następujące elementy:

  • Instalowanie nowej wersji programu .NET Framework nie ma wpływu na istniejące aplikacje.

  • Aplikacje są uruchamiane względem wersji programu .NET Framework, z którą zostały skompilowane. Nie korzystają one z nowej wersji programu .NET Framework, chyba że zostanie to wyraźnie skierowane. Jednak łatwiejsze jest przejście aplikacji do korzystania z nowej wersji programu .NET Framework.

Wpływ na użytkowników i deweloperów

  • Użytkownicy końcowi i administratorzy systemu. Ci użytkownicy mogą teraz mieć większą pewność, że podczas instalowania nowej wersji środowiska uruchomieniowego niezależnie lub z aplikacją nie będzie to miało wpływu na ich komputery. Istniejące aplikacje będą nadal działać tak, jak wcześniej.

  • Deweloperzy aplikacji. Hosting równoległy nie ma prawie żadnego wpływu na deweloperów aplikacji. Domyślnie aplikacje są zawsze uruchamiane względem wersji programu .NET Framework, na której zostały utworzone; to się nie zmieniło. Deweloperzy mogą jednak zastąpić to zachowanie i kierować aplikację do uruchamiania w nowszej wersji programu .NET Framework (zobacz scenariusz 2).

  • Deweloperzy biblioteki i konsumenci. Hosting równoległy nie rozwiązuje problemów ze zgodnością napotykanych przez deweloperów bibliotek. Biblioteka ładowana bezpośrednio przez aplikację — za pośrednictwem bezpośredniego odwołania lub wywołania Assembly.Load — nadal używa środowiska uruchomieniowego, do którego AppDomain jest ładowana. Biblioteki należy przetestować dla wszystkich wersji programu .NET Framework, które mają być obsługiwane. Jeśli aplikacja jest kompilowana przy użyciu środowiska uruchomieniowego .NET Framework 4, ale zawiera bibliotekę utworzoną przy użyciu wcześniejszego środowiska uruchomieniowego, ta biblioteka będzie również używać środowiska uruchomieniowego programu .NET Framework 4. Jeśli jednak masz aplikację utworzoną przy użyciu wcześniejszego środowiska uruchomieniowego i bibliotekę utworzoną przy użyciu programu .NET Framework 4, musisz wymusić użycie programu .NET Framework 4 (zobacz scenariusz 3).

  • Zarządzani deweloperzy składników COM. W przeszłości zarządzane składniki COM automatycznie uruchamiały się przy użyciu najnowszej wersji środowiska uruchomieniowego zainstalowanego na komputerze. Teraz można wykonywać składniki MODELU COM względem wersji środowiska uruchomieniowego, za pomocą którego zostały utworzone.

    Jak pokazano w poniższej tabeli, składniki utworzone za pomocą programu .NET Framework w wersji 1.1 mogą działać obok składników w wersji 4, ale nie mogą być uruchamiane w wersji 2.0, 3.0 lub 3.5, ponieważ hosting równoległy nie jest dostępny dla tych wersji.

    Wersja systemu .NET Framework 1.1 2.0 - 3.5 100
    1.1 Nie dotyczy Nie. Tak
    2.0 - 3.5 Nie. Nie dotyczy Tak
    100 Tak Tak Nie dotyczy

Uwaga

Programy .NET Framework w wersji 3.0 i 3.5 są kompilowane przyrostowo w wersji 2.0 i nie muszą działać obok siebie. Są to z natury ta sama wersja.

Typowe scenariusze hostingu równoległego

  • Scenariusz 1. Aplikacja natywna korzystająca ze składników COM skompilowanych z wcześniejszymi wersjami programu .NET Framework.

    Zainstalowane wersje programu .NET Framework: .NET Framework 4 i wszystkie inne wersje programu .NET Framework używane przez składniki COM.

    Co zrobić: w tym scenariuszu nic nie robi. Składniki COM będą uruchamiane z wersją programu .NET Framework, z którą zostały zarejestrowane.

  • Scenariusz 2. Aplikacja zarządzana utworzona przy użyciu programu .NET Framework 2.0 z dodatkiem SP1, którą wolisz uruchomić przy użyciu programu .NET Framework 2.0, ale są gotowi uruchomić w programie .NET Framework 4, jeśli wersja 2.0 nie jest obecna.

    Zainstalowane wersje programu .NET Framework: wcześniejsza wersja programu .NET Framework i .NET Framework 4.

    Co zrobić: w pliku konfiguracji aplikacji w katalogu aplikacji użyj elementu uruchamiania<>i obsługiwanego< elementuRuntime> w następujący sposób:

    <configuration>  
      <startup >  
        <supportedRuntime version="v2.0.50727" />  
        <supportedRuntime version="v4.0" />  
      </startup>  
    </configuration>  
    
  • Scenariusz 3. Aplikacja natywna korzystająca ze składników COM skompilowanych z wcześniejszymi wersjami programu .NET Framework, które mają być uruchamiane przy użyciu programu .NET Framework 4.

    Zainstalowane wersje programu .NET Framework: .NET Framework 4.

    Co zrobić: w pliku konfiguracji aplikacji w katalogu aplikacji użyj <startup> elementu z atrybutem ustawionym useLegacyV2RuntimeActivationPolicy na true i <supportedRuntime> element ustawiony w następujący sposób:

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

Przykład

W poniższym przykładzie pokazano niezarządzanego hosta COM z uruchomionym składnikiem com zarządzanym przy użyciu wersji programu .NET Framework, która została skompilowana do użycia.

Aby uruchomić poniższy przykład, skompiluj i zarejestruj następujący zarządzany składnik COM przy użyciu programu .NET Framework 3.5. Aby zarejestrować składnik, w menu Projekt kliknij pozycję Właściwości, kliknij kartę Kompilacja, a następnie zaznacz pole wyboru Zarejestruj dla międzyoperamentu 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);  
        }  
    }  
}  

Skompiluj następującą niezarządzaną aplikację języka C++, która aktywuje obiekt COM utworzony w poprzednim przykładzie.

#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;  
}  

Zobacz też