共用方式為


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

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

從 Windows 10 版本 1803 (10.0;組建 17134) 之後,您的 UWP 應用程式可以選擇支援多個實例。 如果多實例 UWP 應用程式的一個實例正在執行,且有後續的啟用要求出現,平臺將不會啟動現有的實例。 相反地,它會建立新的實例,並在個別進程中執行。

開啟使用多重實例行為

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

備註

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

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

這兩個範本都會將 SupportsMultipleInstances 新增至 package.appxmanifest 檔案。 請注意命名空間前置詞 desktop4:只有以桌面為目標的專案才支援多重實例化。

備註

如果您的應用程式以 Windows 10 版本 2004 (組建 19041)或更新版本為目標,您可以使用新的 uap10:SupportsMultipleInstances 屬性,而不是 desktop4:SupportsMultipleInstances。 較新的應用程式偏好使用 uap10 命名空間。

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

多實例激活重新導向

UWP 應用程式的多重實例支援不僅僅是使能夠啟動多個應用程式實例成為可能。 它允許您自訂應用程式的行為,以決定是要啟動新實例還是激活已在執行的實例。 例如,如果啟動應用程式來編輯已在另一個實例中編輯的檔案,您可能會想要將啟用重新導向至該實例,而不是開啟另一個已經編輯檔案的實例。

如果想了解它的運作情況,可以觀看這部影片,內容關於建立多個實例的 UWP 應用程式。

多重實例重新導向 UWP 應用程式 範本會將 SupportsMultipleInstances 新增至 package.appxmanifest 檔案中,也會在專案中加入包含 函式的 Program.cs (如果您使用 C++ 範本,則加入 Main())。 重新導向啟用的邏輯位於 Main 函式。 Program.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() 是第一個運行的東西。 它會在 OnLaunchedOnActivated之前執行。 這可讓您判斷在執行應用程式的任何其他初始化程序代碼之前,是否要啟動此實例或其他實例。

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

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

背景任務及多重實例

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

其他考慮

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

範例

如需多重實例激活重新導向的例子,請參閱 多重實例範例

另請參閱

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