建立多重實例通用 Windows 應用程式

本主題描述如何建立多實例 通用 Windows 平台 (UWP) 應用程式。

從 Windows 10 版本 1803 (10.0;組建 17134) 之後,您的 UWP 應用程式可以選擇支援多個實例。 如果多執行個體 UWP 應用程式的其中一個執行個體正在執行,而且後續啟用要求成功時,平台將不會啟用現有的執行個體。 反而會建立執行於不同處理序中的新執行個體。

重要

JavaScript 應用程式支援多重實例,但不支援多重實例重新導向。 由於 JavaScript 應用程式不支援多重實例重新導向, 因此 AppInstance 類別不適用於這類應用程式。

選擇加入多重實例行為

如果您要建立新的多實例應用程式,您可以安裝可從 Visual Studio Marketplace 取得的多實例應用程式專案範本.VSIX。 安裝範本之後,這些範本將可在 Visual C# > Windows Universal 下的 [新增專案] 對話方塊中取得(或其他語言 > Visual C++ > Windows 通用)。

注意

不再提供多重實例應用程式項目範本。 VSIX 範本十分方便,因此您必須改為修改現有的專案,如下所述。 請務必將DISABLE_XAML_GENERATED_MAIN常數新增至專案建置符號,因為這樣可防止建置產生預設Main()。 這允許使用特別撰寫的應用程式特定 Main(版本)。

已安裝兩個範本: 多實例 UWP 應用程式,其提供建立多重實例應用程式的範本,以及 多實例重新導向 UWP 應用程式,提供您可以建置的其他邏輯,以啟動新的實例,或選擇性地啟動已啟動的實例。 例如,您可能一次只想要一個實例編輯相同的檔,因此您可以將該檔案開啟的實例帶到前景,而不是啟動新的實例。

這兩個範本都會新增 SupportsMultipleInstancespackage.appxmanifest 檔案。 請注意命名空間前置 desktop4 詞 和 iot2:只有以桌面或物聯網 (IoT) 專案為目標的項目支援多重實例。

<Package
  ...
  xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
  xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"  
  IgnorableNamespaces="uap mp desktop4 iot2">
  ...
  <Applications>
    <Application Id="App"
      ...
      desktop4:SupportsMultipleInstances="true"
      iot2:SupportsMultipleInstances="true">
      ...
    </Application>
  </Applications>
   ...
</Package>

多重實例啟用重新導向

UWP 應用程式的多重實例支援超越了啟動多個應用程式實例的可能性。 如果您想要選取應用程式的新實例已啟動,或啟動已執行的實例,則允許進行自定義。 例如,如果啟動應用程式來編輯已在另一個實例中編輯的檔案,您可能會想要將啟用重新導向至該實例,而不是開啟另一個已經編輯檔案的實例。

若要查看運作情形,請觀看此影片以建立多重實例 UWP 應用程式。

多重實例重新導向 UWP 應用程式範本會將 新增SupportsMultipleInstances至 package.appxmanifest 檔案,如上所示,也會將Program.cs (或 Program.cpp,如果您使用 C++ 版本的範本)新增至包含Main()函式的專案。 重新導向啟用的邏輯會進入函式 MainProgram.cs的範本如下所示。

AppInstance.RecommendedInstance 屬性代表這個啟用要求的殼層提供的慣用實例,如果有的話(或null如果沒有的話)。 如果殼層提供喜好設定,則可以將啟用重新導向至該實例,或選擇時可以忽略它。

public static class Program
{
    // This example code shows how you could implement the required Main method to
    // support multi-instance redirection. The minimum requirement is to call
    // Application.Start with a new App object. Beyond that, you may delete the
    // rest of the example code and replace it with your custom code if you wish.

    static void Main(string[] args)
    {
        // First, we'll get our activation event args, which are typically richer
        // than the incoming command-line args. We can use these in our app-defined
        // logic for generating the key for this instance.
        IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs();

        // If the Windows shell indicates a recommended instance, then
        // the app can choose to redirect this activation to that instance instead.
        if (AppInstance.RecommendedInstance != null)
        {
            AppInstance.RecommendedInstance.RedirectActivationTo();
        }
        else
        {
            // Define a key for this instance, based on some app-specific logic.
            // If the key is always unique, then the app will never redirect.
            // If the key is always non-unique, then the app will always redirect
            // to the first instance. In practice, the app should produce a key
            // that is sometimes unique and sometimes not, depending on its own needs.
            string key = Guid.NewGuid().ToString(); // always unique.
                                                    //string key = "Some-App-Defined-Key"; // never unique.
            var instance = AppInstance.FindOrRegisterInstanceForKey(key);
            if (instance.IsCurrentInstance)
            {
                // If we successfully registered this instance, we can now just
                // go ahead and do normal XAML initialization.
                global::Windows.UI.Xaml.Application.Start((p) => new App());
            }
            else
            {
                // Some other instance has registered for this key, so we'll 
                // redirect this activation to that instance instead.
                instance.RedirectActivationTo();
            }
        }
    }
}

Main() 是執行的第一件事。 它會在 OnLaunched OnActivated 之前執行。 這可讓您判斷在執行應用程式的任何其他初始化程序代碼之前,是否要啟動此實例或其他實例。

上述程式代碼會判斷應用程式的現有或新的實例是否已啟動。 金鑰可用來判斷是否有您想要啟動的現有實例。 例如,如果您的應用程式可以啟動以 處理檔案啟用,您可以使用檔名作為密鑰。 然後,您可以檢查應用程式的實例是否已使用該金鑰註冊,並啟動它,而不是開啟新的實例。 這是程式代碼背後的概念: var instance = AppInstance.FindOrRegisterInstanceForKey(key);

如果找到向金鑰註冊的實例,則會啟動該實例。 如果找不到索引鍵,則目前的實例(目前正在執行的 Main實例)會建立其應用程式物件並開始執行。

背景工作和多重實例

  • 跨程式背景工作支援多重實例。 一般而言,每個新的觸發程式都會產生背景工作的新實例(雖然從技術上講,多個背景工作可能會在相同的主機進程中執行)。 不過,會建立背景工作的不同實例。
  • 內部背景工作不支援多重實例。
  • 背景音訊工作不支援多重實例。
  • 當應用程式註冊背景工作時,通常會先檢查工作是否已註冊,然後刪除並重新註冊工作,或不執行任何動作來保留現有的註冊。 這仍然是多實例應用程式的一般行為。 不過,多實例應用程式可能會選擇在每個實例上註冊不同的背景工作名稱。 這會導致相同觸發程式的多個註冊,而且觸發程式引發時將會啟動多個背景工作實例。
  • App-services 會針對每個連線啟動個別的 App-Service 背景工作實例。 對於多重實例應用程式而言,這會保持不變,也就是多實例應用程式的每個實例都會取得自己的App-Service背景工作實例。

其他考量

  • 以桌面和物聯網(IoT) 專案為目標的 UWP 應用程式支援多重實例。
  • 若要避免競爭狀況和爭用問題,多實例應用程式必須採取步驟,以分割/同步存取設定、應用程式本機記憶體,以及任何其他資源(例如使用者檔案、數據存放區等等),這些資源可以在多個實例之間共用。 可以使用標準同步處理機制,例如 Mutex、旗號、事件等等。
  • 如果應用程式在其 SupportsMultipleInstances Package.appxmanifest 檔案中有 ,則其擴展名不需要宣告 SupportsMultipleInstances
  • 如果您新增 SupportsMultipleInstances 至任何其他擴充功能,除了背景工作或應用程式服務之外,裝載擴充功能的應用程式也不會在其 Package.appxmanifest 檔案中宣告 SupportsMultipleInstances ,則會產生架構錯誤。
  • 應用程式可以使用 其指令清單中的 ResourceGroup 宣告,將多個背景工作分組到相同的主機。 這與多重實例衝突,其中每個啟用都會進入個別的主機。 因此,應用程式無法在其指令清單中宣告 SupportsMultipleInstancesResourceGroup

範例

如需多重實例啟用重新導向的範例,請參閱 多重實例範例

另請參閱

AppInstance.FindOrRegisterInstanceForKeyAppInstance.GetActivatedEventArgsAppInstance.RedirectActivationTo處理應用程式啟用