1

I'm developing a UWP application, which uses SignalR to send realtime messages to an API.

Everything works fine, even if my app enters the suspended state (for example user goes to lock screen), signalr succeed in keeping connections alive.

Problem is, when the internet connection is lost while app is suspended, web socket connection goes down and I'd like to reopen the connection as soon as internet access is up again.

But I can't manage making this works, calling:

await HubConnection.Start(); 

hangs indefinitely, it never returns and connection does not restart. I've investigated a little, and it seems IHubConnection.Start() calls a new thread, which is queued because app is suspended. The same way I tried to call the dispatcher like this:

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
    await HubConnection.Start(); // 1
});

The statement // 1 is never called during suspended state, but as soon as the app is resumed, it is executed.

Is it possible to restart the SignalR connection while app is suspended? Or does it need a new thread which has to be queued until app resumes?

  • When the app gets suspended, all it processes should be stopped (apart from extended execution case). I suppose that you already have debugged suspending events. – Romasz Mar 12 '16 at 21:58
  • Yes that's what I was thinking about. It seems obvious after all, this is the purpose of a suspended state. So, the solution may be an extended execution session? I've already tried using this, but the statement still hangs. Maybe the extended execution session should only be called on the OnSuspending event? Because I've used it elsewhere, far after the suspending events was called (i.e on a lost internet access event, while app is already suspended). –  Mar 12 '16 at 22:16
  • Few days ago, I have read somebody's post that he observed that extended execution request throws denied if run outside suspending event. MSDN says it may be called, but code seems to throw *Denied*, at least for now. Have you tried to call it from suspending? I'm also not sure how long extended execution can be. – Romasz Mar 12 '16 at 22:20
  • Yeah I think I've read the same thread :) The weird (or not..) thing, is that running extended execution session while app is already suspended, like I did, returns an *Allowed* result. Everything seems to work fine regarding the extended session. But I'm thinking that it just allows me to have more resources to deal with (like memory), and I'm not sure it guarantees that I can play with more threads or so. –  Mar 12 '16 at 22:22
  • How you run extended execution when the app is already suspended? – Romasz Mar 12 '16 at 22:26
  • I've created a gist: https://gist.github.com/bbougot/51b582e8a03ec4bc526f The RunAsync method is called, but await HubConnection.Start() does not hit until app is resumed again. (i.e I've cleaned my class, there's a lot more code of course). And HubService is a singleton which is instantiated as soon as the app starts. –  Mar 12 '16 at 22:29
  • And the *NetworkInformation.NetworkStatusChanged* gets called when the app is already suspended? Btw - have you thought about background task and network change trigger, though it may not be sufficient in some cases. – Romasz Mar 12 '16 at 22:35
  • Yes the NetworkStatusChanged event fires even if app is suspended. Regarding BackgroundTask, I've tried to use it, but I do not have access to my HubConnection from there :/ My first idea was to use a BackgroundTask, which has the ability to start a new thread, but the big problem is that it can't manipulate data from my main app project. I tried to pass my HubConnection to my BackgroundTask, but of course it only accepts value types args, not reference one. –  Mar 12 '16 at 22:35
  • I wouldn't rely on it, moreover - I would unsubscribe in suspending event. I'm not sure this - if it throws exception, then your app may crash upon resuming. – Romasz Mar 12 '16 at 22:37
  • Hmm right, nice spot. I'll unsubscribe the event for more safety. And for BackgroundTask (like I said in my edited message), I think it's only made for a specific processing, which is not linked to the main app project. I mean, the BackgroundTask gets notified of an event, process things, and at best, store the results in the app LocalStorage which is read at completion by the app process (and results can only be value types or strings). But it can't manipulate objects from it (ideally, I would love to do it, it would solve my issue instantly if I could call HubConnection.Start() there) –  Mar 12 '16 at 22:46
  • You have to check with this event and suspension - throw exception and see what happens upon resuming. Yeah, you cannot manipulate UI from BTask, but maybe you can perform some work upon resuming, use settings/localstorage for syncing. As for now it seems that I haven't got beter ideas. – Romasz Mar 12 '16 at 22:55
  • Ok, thanks anyway ;) I'll try to investigate a bit more, and doing what you said. I'll come back with a solution if there's any. –  Mar 12 '16 at 22:56
  • I've come up with an idea. What if BTask and main app project would share a reference of a same class library, which holds a singleton of the HubService. I posted a thread which explains the idea (http://stackoverflow.com/questions/35943376/how-to-communicate-across-projects-inside-one-net-solution). I didn't succeed to implement it, because I don't know how to deal with a singleton among different projects. But it would solve the issue, as the BTask would be able to manipulate the same instance of HubConnection through a *bridge* (class library). In my thread, A is app and B is BTask –  Mar 13 '16 at 00:09

0 Answers0