Search code examples
c#win-universal-appwindows-10template10

Sharing target Universal Apps Template10 approach in Windows 10


My app is a target app for sharing and am facing issues when the app is running and the user wants to share content. I can't use a frame from the running application because then i get a "marshalling thread" exception.

The application called an interface that was marshalled for a different thread.\r\n\r\nFailed to initialize the application's root visual

My OnStartAsync method in App.xaml.cs looks like this.

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
    switch (DetermineStartCause(args))
    {
        // other cases
        case AdditionalKinds.Other:
            if (args is ShareTargetActivatedEventArgs)
            {
                var shareArgs = args as ShareTargetActivatedEventArgs;

                if (shareArgs.PreviousExecutionState != ApplicationExecutionState.Running)
                {
                    Uri webUrl = await shareArgs.ShareOperation.Data.GetWebLinkAsync();
                    Debug.WriteLine(webUrl.AbsoluteUri);

                    //shareArgs.ShareOperation.ReportStarted();
                    NavigationService.Navigate(typeof(Views.MainPage), webUrl.AbsoluteUri);
                }
                else
                {
                        await CoreApplication.Views.First().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
                        {
                            Uri webUrl = await shareArgs.ShareOperation.Data.GetWebLinkAsync();
                            var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Exclude);
                            Window.Current.Content = new Views.ShareLaunch();
                            Window.Current.Activate();
                        });
                }
            }
            break;
    }
}

I am not sure how to handle the else condition for ShareTargetActivatedEventArgs ie the case in which the application is already running. I found a similar question on Stackoverlow but it doesn't use Template10 library. How to handle this scenario using Template10 library.


Solution

  • When you use share target on UWP and you current app is 'running' (in fact is was suspended and is being resumed - this event is fired first), the new ApplicationView is being created. This is a cool thing, but must be handled correctly - you get new window with new dispatcher and if you try to run something from previous one you will get 'wrong thread' exception (especially look out for INotifyPropertyChanged). Your app is running now at least two threads and you get all consequences of multithreaded application.

    The best of it is that you can put in new window anything you want - new page, frame or other. Everything depends on your design. But if you want to run something/modify your running app, then you will have to use its own Dispatcher. You can for example obtain it by listing views and taking a one:

    await CoreApplication.Views.First().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { /*do some code*/ });
    

    You can also remember your original window's dispatcher in variable and then after sharing, use it. If your code is async, you will have to look out and ensure it gets finished, before leaving share target section.

    Note also that you can use ApplicationViewSwitcher to show your original window (but that doesn't change the fact that the code from sharing is being run on different thread).

    If you need more information about multiple view programming, take a look at MSDN.