Windows UWP, application crashing while suspending during async call - windows-store-apps

In my Windows store application, I have a await function, which sometimes takes couple of minutes to complete (will consult about performance in some other thread). Meanwhile if a user focuses out of the application, it crashes. When I checked event log, I got following error:
App was terminated because it took too long to suspend.
I am using Prism in the application. I have handled Application.Current.Suspending, with following code (which is always called):
protected void OnApplicationSuspending(object sender, SuspendingEventArgs e)
{
var defferal = e.SuspendingOperation.GetDeferral();
if (sessionStateService.SessionState.ContainsKey("plotId"))
{
sessionStateService.SessionState.Remove("plotId");
}
sessionStateService.SessionState.Add("plotId", Plot.Id);
if (sessionStateService.SessionState.ContainsKey("Page"))
{
sessionStateService.SessionState.Remove("Page");
}
sessionStateService.SessionState.Add("Page", "OperationRecording");
defferal.Complete();
}
I have also overridden OnNavigatingFrom function, for saving the navigation parameter (and it does nothing else).
public override void OnNavigatingFrom(NavigatingFromEventArgs e, Dictionary<string, object> viewModelState, bool suspending)
{
if (viewModelState.ContainsKey("plotId"))
{
viewModelState.Remove("plotId");
}
viewModelState.Add("plotId", Plot.Id);
base.OnNavigatingFrom(e, viewModelState, suspending);
}
I am not able to figure out how to fix this issue.

If you suspend your app you should complete it in 5 seconds.
Read Application.Suspending
Saving data prior to suspension is useful because the Suspending event
handler has only 5 seconds to complete its operation.
So, better save large amount of data due application working.
You can also read Guidelines for app suspend and resume
In UWP you can also make suspended time larger with help of Extended Execution

Related

akka.net first published message ends up in the dead letter queue, handshake problem

I have an issue with an akka.net message send/Tell that ends up in the dead letter queue.
I developed a cluster based application using Akka.Cluster.Tools.PublishSubscribe with two ActorSystems each running in a 'console.application' on the same machine.
I start up one actor system with some actors. Then I start up my 2nd. application and immediatelly after I initialized the Actor system I publish the first Message Mediator.Tell(new Publish(Topics.Backend.SomeName, new MyInitialMessage())) to a Topic where the receiving actor is hosted in the 1st. application.
This message ends up in the dead letter queue always.
Ok now, instead of sending the message immediatelly I put in a delay of e.g 5sec. Then the message could be delivered properly.
This seems to me as a handshake problem.
Question: How do I find out when the 2nd. actor system is ready to receive any messages??
My current workaround is: I send scheduler based for each second a MyInitialMessage and wait for the first response message from my 2nd. application. Then I know my 2nd. app is now ready, handshake done.
But this seems to me just as a workaround. What would be a proper solution to this issue?
chris
Akka.Cluster.Tools.PublishSubscribe works over cluster. You need to await for cluster to become initialized before you'll be able to publish any messages. All of cluster operations are encapsulated in Cluster class that can be created from any actor system using Cluster.Get(actorSystem). In order to wait for cluster to initialize:
You can join to cluster programmatically by using await cluster.JoinAsync(address, cancellationToken) - you can use it to initialize both seed nodes (just make actor system join to itself) and new nodes. This will require to leave seed-nodes in your HOCON configuration empty.
If you're initializing cluster from configuration (using HOCON config file), you can register a callback function using cluster.RegisterOnMemberUp(callback) to postpone the rest of processing until local actor system successfully joined the cluster.
The fastest (in terms of performance and resource usage) way is to subscribe to cluster membership events from within a particular actor. In fact this is how other solutions described above are actually implemented under the hood.
class MyActor : ReceiveActor
{
readonly Cluster cluster = Akka.Cluster.Cluster.Get(Context.System);
public MyActor()
{
Receive<ClusterEvent.MemberUp>(up =>
{
if (up.Member.Address == cluster.SelfAddress)
{
Become(Ready);
}
});
}
protected override void PreStart()
{
cluster.Subscribe(Self, new[]{ typeof(ClusterEvent.IMemberEvent) });
}
protected override void PostStop()
{
// rember to unsubscribe once actor is stopping
cluster.Subscribe(Self);
}
void Ready()
{
// other receiver handlers
}
}

Notify subscribers after new messages have stopped coming in

In an app where users are expected to make several changes in a short period of time, I'd like to use a message queue to collect these events, and only notify listeners when new changes have stopped coming in for some period X.
The expected workflow would be:
User makes an edit -> message added to queue
User makes another edit -> message added to queue
Some time passes
Consumer is notified of all pending changes
I've looked into documentation for several different message queues, but none of them seem to have this kind of message batching out of the box.
I did find some features that might help to roll my own, e.g. Kafka has a producer config called linger that tells it to wait X ms for more messages to add to a batch, but this is clearly intended as a performance improvement. In addition, this option is at the producer side, whereas for my use case it would make more sense on the consumer side.
Is this a use case message queues can support? The lack of results makes me think that I may be trying to use message queues wrong.
Queues are not a good fit for such use cases. I would recommend using Cadence Workflow to implement your logic with a minimal effort.
Here is a straw-man design that satisfies your requirements:
Send signalWithStart request that contains an edit information to a user workflow using userID as the workflow ID. It either delivers the signal to the workflow or first starts the workflow and delivers signal to it.
All request to that workflow are buffered by it. Cadence provides hard guarantee that only one workflow with given ID can exist in open state. So all signals (events) are guaranteed to be buffered in the workflow that belongs to the user.
After configured timeout an activity that notifies users about the pending changes is invoked.
The pending changes are applied by the next activity.
The workflow complete.
Here is the workflow code that implements it in Java (Go client is also supported):
public interface BufferedEditsWorkflow {
#WorkflowMethod
void execute(String userId, Duration notifyAfter, Edit firstEdit);
#SignalMethod
void addEdit(Edit edit);
}
public interface BufferedEditsActivities {
void notifyUser(String userId, List<Edit> edits);
void process(String userId, List<Edit> edits);
}
public class BufferedEditsWorkflowImpl implements BufferedEditsWorkflow {
private final List<Edit> edits = new ArrayList<>();
private final BufferedEditsActivities activities = Workflow.newActivityStub(BufferedEditsActivities.class);
#Override
public void execute(String userId, Duration notifyAfter, Edit firstEdit)
{
edits.add(firstEdit);
// Cadence doesn't have limit on sleep duration.
// It can sleep at this line for a year with no problem.
Workflow.sleep(notifyAfter);
activities.notifyUser(userId, edits);
activities.process(userId, edits);
}
#Override
public void addEdit(Edit edit) {
edits.add(edit);
}
}
Code that starts the workflow for the first edit:
private void addFirstEdit(WorkflowClient cadenceClient, Edit edit) {
WorkflowOptions options = new WorkflowOptions.Builder().setWorkflowId(edit.getUserId()).build();
BufferedEditsWorkflow workflow = cadenceClient.newWorkflowStub(BufferedEditsWorkflow.class, options);
workflow.execute(edit.getUserId(), Duration.ofHours(1), edit);
}
Code that adds more edits.
private void addEdit(WorkflowClient cadenceClient, Edit edit) {
WorkflowOptions options = new WorkflowOptions.Builder().setWorkflowId(edit.getUserId()).build();
BufferedEditsWorkflow workflow = cadenceClient.newWorkflowStub(BufferedEditsWorkflow.class, options);
workflow.addEdit(edit);
}
Cadence offers a lot of other advantages over using queues for task processing.
Built it exponential retries with unlimited expiration interval
Failure handling. For example it allows to execute a task that notifies another service if both updates couldn't succeed during a configured interval.
Support for long running heartbeating operations
Ability to implement complex task dependencies. For example to implement chaining of calls or compensation logic in case of unrecoverble failures (SAGA)
Gives complete visibility into current state of the update. For example when using queues all you know if there are some messages in a queue and you need additional DB to track the overall progress. With Cadence every event is recorded.
Ability to cancel an update in flight.
See the presentation that goes over Cadence programming model.

wakeLock does not wait for network connectivity

I am using a wakelock for a alarm to update the app state regularly. The wifi takes a while to connect on Samsung phones. Also the "keep awake" option on Wifi does not work on Samsung phones (nor are they interested in fixing the issue). So when the wakelock does happen, it should wait for wifi to connect. Do I need to create a listener for the wifi connectivity for this to work, or should wakelock, kinda block for that wifi to connect ?
mWakeLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "Taxeeta");
mWakeLock.acquire();
// do some network activity, in a asynctask
// in the doPost of asyscTask, release lock
Edit :
The question is, that in the AsyncTask if the network is not connected, OR takes time to get on (3g takes a while to get on), the webservice call in the Async doInBackground will fail. And I will have to release the lock anyways.
SO
Should I put in wifi/data connection listeners in ? Or is there a better way ?
I have a similar scenario - I am woken up by an alarm, the alarm's BroadcastReceiver launches a WakefulIntentService and the service starts a scan for networks. I use a stupid way of holding on to the lock1 - I intend to replace this with a latch. I suggest you replace the "AsyncTask" with a WakefulIntentService. Chances are the AsyncTask is not ever fired. In the WakefulIntentService you must acquire and hold on to a wifi lock - I would make this a static field of the YourWakefulIntentService - not entirely clear on this - it's a while back. If this does not work I would use a latch in the YourWakefulIntentService :
// register an alarm
Intent i = new Intent(context, YourReceiver.class);
PendingIntent alarmPendingIntent= PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
WakefulIntentService.sendWakefulWork(context, YourWIS.class);
}
}
//pseudocode !
public class YourWIS extends WakefulIntentService { // you must add a cstor !
#Override
doWakefulWork() {
acquireWifiLock();
enableScanReceiver();
startScan();
serviceLatch.wait();
releaseWifiLock();
}
}
// in YourScanReceiver
onReceive() {
if(action.equals(SCAN_RESULTS) {
// do something that does not take time or start another/the same
// WakefulIntentService
serviceLatch.notify();
}
}
Try first the WakefulIntentService (I guess you launch the AsyncTask from the alarm receiver). The scan receiver is a receiver registered to receive the scan results (see WifiManager docs - prefer Receivers to listeners for sleep issues)
1 : this is a working class - I just use a second wakeful intent service to keep the wake locks - have still to refactor it to use latches but this approach at least works (I have the second service (the Gatekeeper) wait on a monitor and have the wake lock inside the Gatekeeper. The gatekeeper also holds its CPU lock so all is fine (and ugly)

WebAPI and HTML5 SSE

was trying to encapsulate a partial view to show feedback that i can push back to the client.
This Article shows a method of pushing back data using HTML5 Server-Sent events (SSE).
I noticed that if i opened up several browser tabs and then closed one i got exceptions as the logic didn't remove the respective stream from the ConcurrentQueue. I amended the code as below
private static void TimerCallback(object state)
{
StreamWriter data;
Random randNum = new Random();
// foreach (var data in _streammessage)
for (int x = 0; x < _streammessage.Count; x++)
{
_streammessage.TryDequeue(out data);
data.WriteLine("data:" + randNum.Next(30, 100) + "\n");
try
{
data.Flush();
_streammessage.Enqueue(data);
}
catch (Exception ex)
{
// dont re-add the stream as an error ocurred presumable the client has lost connection
}
}
//To set timer with random interval
_timer.Value.Change(TimeSpan.FromMilliseconds(randNum.Next(1, 3) * 500), TimeSpan.FromMilliseconds(-1));
}
I also had to amend the OnStreamAvailable member as the framework syntax had changed to the second parameter being a HttpContent rather than HttpContentHeaders
public static void OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context)
The problem now is i am still getting inconsistant behaviour if i add or remove clients i.e it times out when trying to initialise a new client. Does anyone have any ideas or more examples of using SSE with WinAPI and the correct "framework of methods" to handle disconnected clients
Cheers
Tim
This article is actually an adaptation of my original article from May - http://www.strathweb.com/2012/05/native-html5-push-notifications-with-asp-net-web-api-and-knockout-js/ (notice even variable names and port numbers are the same :-).
It is a very valid point that you are raising, and detecting a broken connection is something that's not very easy with this setup. The main reason is that while ASP.NET (the host) allows you to check a broken connection, there is no notification mechanism between ASP.NET (host) and Web API informing about that.
That is why in order to detect a broken connection (disconnected client) you should really try writing to the stream, and catch any error - this would mean the client has been disconnected.
I asked the same question to Brad Wilson/Marcin Dobosz/Damien Edwards at aspconf, and Damien suggested using HttpContext.Current.Response.IsClientConnected - so basically bypassing Web API and obtaining the connectivity info from the underlying host directly (however there is still a race condition involved anyway). That is really .NET 4. He also pointed an interesting way in which this problem could be avoided in .NET 4.5 using an async cancellation token. Frankly, I have never got around to test it, but perhaps this is something you should explore.
You can see their response to this problem in this video - http://channel9.msdn.com/Events/aspConf/aspConf/Ask-The-Experts - fast forward to 48:00

NServiceBus: Messages handled multiple times

I am at a complete loss as to why I am experiencing this problem. I am new to NServiceBus and have so far set up a dead simple 'server' which listens for messages sent by a web application. The server asks for custom initialisation (IWantCustomInitialization) and uses a custom builder for Castle Windsor 2.5.1. This custom builder is basically a copy of the one that comes with the NServiceBus source code, with two minor changes to move away from methods deprecated in Windsor 2.5.
Note that my code shares the container instance with NServiceBus.
The problem I experience is that every message sent by the web application is processed five (5) times by the server. The log files have five entries for each attempt, with the fifth attempt looking like this:
2011-03-28 16:04:10,326 [Worker.8] DEBUG NServiceBus.Unicast.UnicastBus [] - Calling 'HandleEndMessage' on NServiceBus.SagaPersisters.NHibernate.NHibernateMessageModule
2011-03-28 16:04:10,327 [Worker.8] DEBUG NServiceBus.Unicast.UnicastBus [] - Calling 'HandleEndMessage' on Server.NHibernateSessionMessageModule
2011-03-28 16:04:10,341 [Worker.8] DEBUG NServiceBus.Unicast.UnicastBus [] - Calling 'HandleError' on NServiceBus.SagaPersisters.NHibernate.NHibernateMessageModule
2011-03-28 16:04:10,342 [Worker.8] DEBUG NServiceBus.Unicast.UnicastBus [] - Calling 'HandleError' on Server.NHibernateSessionMessageModule
2011-03-28 16:04:10,344 [Worker.8] ERROR NServiceBus.Unicast.Transport.Msmq.MsmqTransport [] - Message has failed the maximum number of times allowed, ID=80cffd98-a5bd-43e0-a482-a2d96ca42b22\20677.
I have no indication why the message fails, and I don't know where to dig for more information/output.
The configuration 'endpoint' looks like this:
public void Init()
{
container = Windsor.Container;
NServiceBus.Configure.With().CastleWindsor251Builder(container).XmlSerializer().MsmqTransport().IsolationLevel(System.Transactions.IsolationLevel.Unspecified);
var masterInstaller = new NotificationServerInstaller();
masterInstaller.Install(container, null);
}
The message handler is, at this stage, really contrived, and looks like this:
public class NewUserMessageHandler : IHandleMessages<NotifyNewUserMessage>
{
private readonly IGetUserQuery _getUserQuery;
public NewUserMessageHandler(IGetUserQuery getUserQuery)
{
_getUserQuery = getUserQuery;
}
public void Handle(NotifyNewUserMessage message)
{
var result = _getUserQuery.Invoke(new GetUserRequest { Id = new Guid("C10D0684-D25F-4E5E-A347-16F85DB7BFBF") });
Console.WriteLine("New message received: {0}", message.UserSystemId);
}
}
If the first line in the handler method is commented out, the message is processed only once.
I have found some posts/threads on the web (including StackOverflow) which talk about similar issues, notably http://tech.groups.yahoo.com/group/nservicebus/message/5977 and Anyone using Ninject 2.0 as the nServiceBus ObjectBuilder? - but I haven't had any success in making my problem go away.
I'd be most obliged for any help. I'm a n00b at NServiceBus!
NServiceBus isn't handling it multiple times by default it will retry 5 times if an exception occurs, you can set this in a config file. Have you got distributed transactions turned on? Because you are committing to a database and you have an open transaction (the queue transaction) when you open another transaction it will try and upgrade it to a distributed transaction, I think that may be the issue. Have you run with the console app? You should see some out put on there.
I would recommend wrapping the body of the Handle method in a try/catch and add a break point to the catch and see what is wrong.
Once you work it out, remove the try/catch.