tomkuijsten / restup

Webserver for universal windows platform (UWP) apps
MIT License
114 stars 48 forks source link

Restup together with GpioController hangs #124

Closed jonaswikstrom closed 7 years ago

jonaswikstrom commented 7 years ago

Hello

Trying to use restup together with logic using the GpioController. I have multiple GpIoPins opened listening on the ValueChanged event. Everything works great until I do a request to the server making all events to stop working and after a while the application exists with code -1.

dm-CaT commented 7 years ago

@jonaswikstrom, can you provide source code of your application? Please check if you are not releasing BackgroundTaskDeferral in case if application is headless. Your StartupTask should looks like the next:

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

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

            var restHandler = new RestRouteHandler();
            this.RegisterControllers(restHandler);

            var configuration = new HttpServerConfiguration()
                .ListenOnPort(80)
                .RegisterRoute("api", restHandler)
                .EnableCors();

            var server = new HttpServer(configuration);
            await server.StartServerAsync();
        }
    }
jonaswikstrom commented 7 years ago

Sure!

This is my simple code which makes ValueChanged stop:

`public sealed class StartupTask : IBackgroundTask { private BackgroundTaskDeferral backgroundTaskDeferral = null;

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

        var restRouteHandler = new RestRouteHandler();
        restRouteHandler.RegisterController<ConfigurationController>();

        var configuration = new HttpServerConfiguration()
            .ListenOnPort(8800)
            .RegisterRoute("api", restRouteHandler);

            var httpServer = new HttpServer(configuration);

            await httpServer.StartServerAsync();

        var gpIoController = GpioController.GetDefault();
        var pin = gpIoController.OpenPin(2);
        pin.DebounceTimeout = TimeSpan.FromMilliseconds(50);

        pin.ValueChanged += (sender, args) =>
        {
            if (args.Edge == GpioPinEdge.FallingEdge)
            {
                Debug.WriteLine("Pin 2 is pressed");
            }
        };

    }`
dm-CaT commented 7 years ago

I've just make circuit which handles and writes to debugger window whenever button is pressed and released. The only one difference against your example is that I'd set DriverMode for pin. Please, add next statement after the PIN is open and check again.

            if (pin.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
            {
                pin.SetDriveMode(GpioPinDriveMode.InputPullUp);
            }
            else
            {
                pin.SetDriveMode(GpioPinDriveMode.Input);
            }
Jark commented 7 years ago

@jonaswikstrom you need to keep a reference to httpServer and pin by using a field instead of a variable in the Run method.

What happens is when the Run method exits, the deferral will stay alive, but at some point the garbage collector will come around and garbage collect any variables which don't have references any more.

So that's most likely why you see that it stops working.

jonaswikstrom commented 7 years ago

Thnx guys!

@Jark putting the references as fields made it happen!!!

tomkuijsten commented 7 years ago

Closed as it's resolved.