dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
21.98k stars 1.72k forks source link

Need a way to synchronize a page dispose before a new page starts #16608

Open genifycom opened 1 year ago

genifycom commented 1 year ago

Description

A classic example of this is using a resource like a Scanner (in SPP mode). On Page A, the scanner is initialized and connected. On a page switch, the scanner needs to be cleanly shutdown (serial port closed and reset). On the switch to another (or the same page), the scanner needs to be in a state that it can be reconnected.

The page dispose does not guarantee that Page A dispose is complete before the next page starts its process but the resource (could be a database, scanner, other device) access needs to be serialized.

How do we handle this using Blazor pages? Is there a way to synchronize cleanly the cleanup of one page before starting up another (not every time of course, but when needed).

Thanks

Public API Changes

Synchronization object that a page might use to coordinate page changes.

Intended Use-Case

For use with page resources that require synchronization for initialize and shutdown.

mattleibow commented 1 year ago

Although having perfect page synchronization, I also think that the lifetime of a service that needs clean shutdown should not be on the page.

One thing that may happen is the device can be backgrounded at any time - or the user could rotate the device and trigger a full page reconstruction (in some cases).

It may be better to have a singleton service that is independent of the page and rather the page requests the scanner or requests a shutdown. Below I have totally pseudo-coded an idea, but may form some starting/searching point. In this case, you do not want to attach the scanner to the page, but rather let the scanner work at its own pace and you wait for events/tasks. An alternate (and probably simpler) implementation is to use events so that all things can access the scanner without having to create/destroy on every page navigation. You could have a buffer so if the user accidentally taps a different page/tab, you don't shutdown immediately.

class ScannerService
{
    object _locker = new();
    TheScannerThing? _scanner;
    TaskCompletionSource<TheScannerThing?> _tcs;
    TaskCompletionSource _tcsShutdown;

    public Task<TheScannerThing?> RequestStartup() {
        lock (_locker) {
            // wait for any previous shutdowns to happen
            if (_tcsShutdown is not null) {
                await _tcsShutdown.Task;
                _tcsShutdown = null;
            }

            // return current request
            if (_tcs is not null)
                return _tcs.Task;

            // start a new one
            _tcs = new();
            if (_scanner is null) {
                _scanner = CreateScannerInstance();
                _scanner.OnReady += {
                    // the scanner is ready, so return all the tasks
                    _tcs.TrySetResult(_scanner);
                };
                _scanner.OnError += {
                    _tcs.TrySetException(...);
                };
                _scanner.Start();
            }
        }
    }

    public Task RequestShutdown() {
        lock (_locker) {
            // wait for any startups to complete
            // start shutdown
        }
    }
}
ghost commented 1 year ago

Hi @genifycom. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

mattleibow commented 1 year ago

Let me know if this is helpful and solves your issue. I am not sure if a guarantee of page destruction prior to page creation is exactly what you are looking for.

genifycom commented 1 year ago

Thanks for the sample.

ghost commented 1 year ago

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.