How to use a CoreDispatcher with time-triggered BackgroundTask in uwp?

HaythamKenway 6 Reputation points
2021-09-08T16:57:17.137+00:00

Hi there,

I am using C# and UWP to create a Windows store application.

In simple terms, the overall architecture is : View -> Controller -> (Database and BackgroundTask), every name represents a different module in the solution.

BackgroundTask is a WRC module and it registers a task that runs every 15 minutes using a time trigger and if there's a need, it'll update the database.

So if there are changes in the database and if the application is in foreground, i need to update the UI. After doing some research, i found that i need to use something called a Dispatcher as the backgroundTask and main UI Thread are using different memories and are not allowed to communicate with each other.

Now the problem is: ** Dispatcher is only available in View module and i need it in BackgroundTask module. Even if i pass in a reference by injecting an interface or something, when the time-trigger is gonna run the task, it'll start anew, meaning the starting point will be a class in the BackgroundTask (that implements IBackgroundTask interface) and hence, **that instance of Task will not have the reference to the Dispatcher that i provided (as it'll be in the main UI thread).

Also, note that i cannot give direct reference of View to BackgroundTask as C# doesn't allow Cyclic Dependency.

I've been thinking about this for over a week now but couldn't find a solution.

Any help would be appreciated.

Thank you.

Edit:

this is how i'm registering the task:

private readonly string EntryPoint = typeof(BackgroundTaskEntryPoint).FullName;
internal async void Register()
        {
            if (!IsAlreadyRegistered(TaskName))
            {
                BackgroundTaskBuilder TaskBuilder = new BackgroundTaskBuilder
                {
                    Name = TaskName,
                    TaskEntryPoint = EntryPoint
                };
                TaskBuilder.SetTrigger(BackgroundTaskTrigger);

                BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();

                if (status == BackgroundAccessStatus.DeniedBySystemPolicy ||
                    status == BackgroundAccessStatus.DeniedByUser)
                {
                    return;
                }

                var task = TaskBuilder.Register();
                task.Completed += new BackgroundTaskCompletedEventHandler(Task_Completed);
            }
        }

        private void Task_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
        {
            Debug.WriteLine("Task Completed event was raised");
        }

the trigger in this case is : [ToastNotificationHistoryChangedTrigger][1] and is being referred to as TOAST_STATUS_CHANGER in the following code snippet.

and this is the entry point:

public sealed class BackgroundTaskEntryPoint : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;
        private readonly string QUARTER_HOUR_TOAST_SCHEDULER = 
            typeof(QuarterHourToastSchedulerBackgroundProcessRegistrar).Name;
        private readonly string USER_PRESENT_TOAST_SCHEDULER =
            typeof(UserPresentToastSchedulerBackgroundProcessRegistrar).Name;
        private readonly string TOAST_INTERACTION_HANDLER =
            typeof(ToastInteractionHandlerBackgroundProcessRegistrar).Name;
        private readonly string TOAST_STATUS_CHANGER =
            typeof(ToastNotificationDisplayedStatusChangerBackgroundProcessRegistrar).Name;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();
            string taskName = taskInstance.Task.Name;

            if (taskName.Equals(QUARTER_HOUR_TOAST_SCHEDULER))
            {
                new ReminderToastScheduler().Schedule();
            }
            else if (taskName.Equals(USER_PRESENT_TOAST_SCHEDULER))
            {

                new MissedReminderToastScheduler().Schedule();
                new ReminderToastScheduler().Schedule();
            }
            else if (taskName.Equals(TOAST_INTERACTION_HANDLER))
            {
                new ToastInteractionHandler(
                    taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail
                    )
                    .HandleInteraction();
            }
            else if (taskName.Equals(TOAST_STATUS_CHANGER))
            {
                new ReminderStatusChanger().ChangeStatusToDisplayed();
            }

            deferral.Complete();
        }

    }

and this is the ReminderStatusChanger class:

internal class ReminderStatusChanger
    {
        private SQLiteDatabase databaseInstance;

        internal ReminderStatusChanger()
        {
            databaseInstance = SQLiteDatabase.GetInstance();
        }

        internal void ChangeStatusToDisplayed()
        {
                foreach (var toast in ToastNotificationManager.History.GetHistory())
                {
                    try
                    {
                        databaseInstance.UpdateStatusToDisplayed(toast.Tag);
                    }
                    catch (Exception) { }
                }
        }
  }
Universal Windows Platform (UWP)
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
8,249 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Nico Zhu (Shanghai Wicresoft Co,.Ltd.) 12,826 Reputation points
    2021-09-09T06:46:54.343+00:00

    Hello, Welcome to Micorosoft Q&A,

    So if there are changes in the database and if the application is in foreground, i need to update the UI.

    Derive from your description, the key point is not related with CoreDispatcher. The key point is getting the signal when background triggered. BackgroundTask contains BackgroundTaskProgressEventHandler event, it will be invoked when the task instance progress value update in the backgroundtask. you could regard as a signal.

     task.Progress += new BackgroundTaskProgressEventHandler(OnProgress);  
    

    For more code please refer to BackgroundTask official code sample scenario5


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.