Search code examples
c#uwpbackgroundraspberry-piwindows-iot-core-10

How to make 2 tasks run simultaneously in a UWP background app?


I need help running my UWP background app deployed on my Raspberry Pi (hosting Windows 10 IOT Core).

It's almost working but I got a tricky issue... Let me explain:

The app has 2 functionalities:

  • A Web Server that receives http requests and do some processing according to parameters. (based on this link)
  • A repeating task that is executed every X minutes (X varies from 10 to 60).

Both functionalities work well if executed seperately but I need them to run simultaneously. I'm rather new to UWP & Raspberry so maybe there's something I'm missing...

  • Is it a matter of thread conflict?
  • Is a background task on a raspberry limited to a single thread (so the first/last process executed wins)?
  • Do all classes need to be "sealed" (microsofts's doc says so but not the example they provide)?

I tought about splitting the project into two independant deployable tasks and I believe it would work but I need the webserver task to control (START/PAUSE/STOP) the repeating task.

I think communication between them could be feasable (using this way) but I'm looking for the simplest/fastest solution here.

Here's the stripped down code (the 3 classes are in separate files):

App class:

public sealed class StartupTask : IBackgroundTask
{
    private static BackgroundTaskDeferral _Deferral = null;

    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        _Deferral = taskInstance.GetDeferral();

        var webserver = new WebServer();
        await ThreadPool.RunAsync(workItem => { webserver.Start(); });

        StartRepeatingTask();
    }
}

Web server class:

internal class WebServer
{
    private const uint BUFFER_SIZE = 8192;

    public async void Start()
    {
        var listener = new StreamSocketListener();
        await listener.BindServiceNameAsync("1537");

        listener.ConnectionReceived += async (sender, args) =>
        {
            // Do some stuff
            ...
            Processing.StopProcess();
        }
    }
}

Processing class

public class Processing 
{
    private static Task myTask = null;
    private static CancellationTokenSource taskCancellation = new CancellationTokenSource();

    public static void StartRepeatingTask()
    {
        taskCancellation = new CancellationTokenSource();
        myTask = Task.Run(() => AutoProcess(), taskCancellation.Token);
    }

    public static void AutoProcess()
    {
        Process();

        myTask = Task.Delay(GetDelayToUse(DELAY_SET_LIST))
            .ContinueWith(t => AutoProcess(), taskCancellation.Token);
    }

    public static void Process()
    {
        // Do some other stuff
    }

    public static void StopProcess()
    {
        taskCancellation.Cancel();
    }
}

Solution

  • The two task can run in a background app simultaneously.

    Is it a matter of thread conflict?

    If there are no commitications or shared data between the two task, there will be no confilct. The important thing is that you need to pay attention to the synchronization of data. If you use a list or queue to share the data between the two threads, you should use the concurrency object. Please refer to ConcurrentQueue example, ConcurrentQueue represents a thread-safe.

    Is a background task on a raspberry limited to a single thread (so the first/last process executed wins)?

    Once a background applications are deployed and configured, these applications launch at machine startup and run continuously without any process lifetime management resource use limitations. There are some limitations about background task, but it is not limited to a single thread. More information here. Here you need to differentiate the background application on Windows IoT Core and task.

    Do all classes need to be "sealed" (microsofts's doc says so but not the example they provide)?

    Yes, the background task class itself—and all other classes in the background task project—need to be public classes that are sealed (or final). It applies to the background tasks which inherited from interface IBackgroundTask, but not the classes are using for normal thread.