Dialog.ask() how to call the same method again - blackberry

I want to check if the network connection is available or not. If it's not available then i am showing a dialog and on click of ok button in the dialog then again i need to check the network connection and so on. Here i am calling the same method again and again., The problem is on click of ok button in the dialog its calling the same method, but the dialog is not getting closed.
Anybody have an idea how to close the dialog if we call the same method again and again.
Eg
private void checkConnection()
{
if (!networkAvailable())
{
int reply = Dialog.ask(Dialog.OK,"Network not available");
if (reply == Dialog.OK)
{
checkConnection();
}
}
Thanks
Mindus

Here is an implementation of the above that is processed in a loop rather than recursively, which makes it easier to manage the end conditions:
private void checkConnection() {
if (!networkAvailable()) {
boolean networkOK = networkAvailable();
int reply = Dialog.ask(Dialog.D_OK,"Network not available");
while (reply == Dialog.OK && !networkOK) {
networkOK= networkAvailable();
if ( !networkOK) {
reply = Dialog.ask(Dialog.D_OK,"Network not available");
}
} // end of while loop
}
} // end of method
This code could be further optimised, but as shown, demonstrates the required steps in an obvious fashion.
You could also limit the number of times round the loop if you wanted too.
However I have a couple of reservations.
From a technical perspective I don't know what the method networkAvailable() does. It might be blocking, in which case we need to rework this code to get it off the Event Thread.
But I guess my major concern is that I am not sure this is a good user experience. I think you need to look at this from the user's perspective, and think about what they would want to happen if there was no network available. I am not convinced giving them a dialog like this is the optimal solution.

By seeing your approach you there is cyclic process of checking internet connection it will only end-up when there in and internet connection.
the other way to close this dialog is to set a counter variable.
Try this code :
public static final int mCounter = 1;
private void checkConnection() {
if (!networkAvailable()) {
if (mCounter != 5) {
int reply = Dialog.ask(Dialog.OK, "Network not available");
if (reply == Dialog.OK) {
mCounter++;
checkConnection();
}
} else {
mCounter = 1;
new Thread(new Runnable() {
public void run() {
Thread.sleep(60000);
checkConnection();
}
}).start();
}
}
}
as this counter variable will be at 5 this dialog will be dismissed.
after one minute this thread will wakes up and again your internet check method will continue.

Related

Using events to trigger ActionResult in ASP.NET MVC

I am working on an ASP.NET MVC web service. In a web page, when a user clicks on a button, this triggers a complex method that takes a bit of time to finish. I want to redirect the user to a waiting page and then, when the process is finished, to redirect the user to a new page.
When the process is done it raises an event, which I can listen to from the controller. But I cannot make the last step to work (the controller redirecting to the new page upon receiving the event).
Here is my very naïve attempt at doing it (with simpler names):
public MyController()
{
EventsControllerClass.ProcessComplete += new EventHandler<MyArgsClass>(OnEventReceived);
}
private void OnEventReceived(object sender, MyArgsClass eventArguments)
{
RedirectToPage();
}
private ActionResult RedirectToPage()
{
return RedirectToAction("PageName");
}
After many days working on this, I have a viable solution. It may not be pretty, but it works, and maybe some ideas can be useful for other people, so here it goes:
I will explain the solution to my particular problem: I need a button to redirect to a "waiting" page while a longer process runs in the background and raises an event when it is finished. When this event is received, we want to redirect the user (automatically) to a final page.
First, I created a class to listen to the event. I tried doing this directly in the controller, but you need to be careful about signing and unsigning, because apparently controllers get created and destroyed at each request. In this "listener class" I have a bool property that is set to "true" when the event is received.
When the first action is triggered, the controller normally redirects to the "wait" page, where I have this simple java script redirecting to the new action:
<script type="text/javascript">
window.location = "#Url.Action("WaitThenRedirect", "AuxiliaryControllerName")";
</script>
This sets in motion the long process (through another event). The key is that I do this with an asynchronous action (this controller inherits from AsyncController). (Note I used an auxiliary controller. This is to keep all asynchronous stuff apart.) This is how this looks (more info here):
public static event EventHandler<AuxiliaryEventsArgs> ProcessReady;
public void WaitThenRedirectAsync()
{
AsyncManager.OutstandingOperations.Increment();
ProcessReady += (sender, e) =>
{
AsyncManager.Parameters["success"] = e.success;
AsyncManager.OutstandingOperations.Decrement();
};
WaitForEvent();
}
public ActionResult WaitThenRedirectCompleted(bool success)
{
if (success)
{
return RedirectToAction("RedirectToView", "ControllerName");
}
else
{
return RedirectToAction("UnexpectedError", "ControllerName");
}
}
private void WaitForEvent()
{
bool isWaitSuccessful = true;
int waitingLoops = 0;
int waitingThreshold = 200;
int sleepPeriod = 100; // (milliseconds)
while (!EventsListener.IsTheThingReady())
{
System.Threading.Thread.Sleep(sleepPeriod);
++waitingLoops;
if (waitingLoops > waitingThreshold)
{
System.Diagnostics.Debug.WriteLine("Waiting timed out!");
isWaitSuccessful = false;
break;
}
}
isWaitSuccessful = true;
if (null != ProcessReady)
{
AuxiliaryEventsArgs arguments = new AuxiliaryEventsArgs();
arguments.success = isWaitSuccessful;
try
{
ProcessReady(null, arguments);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Error in event ProcessReady" + ex);
}
}
}
I believe it is possible to use ajax syntax for alternative solutions, but this is what I have and it works nicely. I believe this is not a very common need, but hopefully someone will benefit!

How do I get the current attempt number on a background job in Hangfire?

There are some database operations I need to execute before the end of the final attempt of my Hangfire background job (I need to delete the database record related to the job)
My current job is set with the following attribute:
[AutomaticRetry(Attempts = 5, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
With that in mind, I need to determine what the current attempt number is, but am struggling to find any documentation in that regard from a Google search or Hangfire.io documentation.
Simply add PerformContext to your job method; you'll also be able to access your JobId from this object. For attempt number, this still relies on magic strings, but it's a little less flaky than the current/only answer:
public void SendEmail(PerformContext context, string emailAddress)
{
string jobId = context.BackgroundJob.Id;
int retryCount = context.GetJobParameter<int>("RetryCount");
// send an email
}
(NB! This is a solution to the OP's problem. It does not answer the question "How to get the current attempt number". If that is what you want, see the accepted answer for instance)
Use a job filter and the OnStateApplied callback:
public class CleanupAfterFailureFilter : JobFilterAttribute, IServerFilter, IApplyStateFilter
{
public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
try
{
var failedState = context.NewState as FailedState;
if (failedState != null)
{
// Job has finally failed (retry attempts exceeded)
// *** DO YOUR CLEANUP HERE ***
}
}
catch (Exception)
{
// Unhandled exceptions can cause an endless loop.
// Therefore, catch and ignore them all.
// See notes below.
}
}
public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
// Must be implemented, but can be empty.
}
}
Add the filter directly to the job function:
[CleanupAfterFailureFilter]
public static void MyJob()
or add it globally:
GlobalJobFilters.Filters.Add(new CleanupAfterFailureFilter ());
or like this:
var options = new BackgroundJobServerOptions
{
FilterProvider = new JobFilterCollection { new CleanupAfterFailureFilter () };
};
app.UseHangfireServer(options, storage);
Or see http://docs.hangfire.io/en/latest/extensibility/using-job-filters.html for more information about job filters.
NOTE: This is based on the accepted answer: https://stackoverflow.com/a/38387512/2279059
The difference is that OnStateApplied is used instead of OnStateElection, so the filter callback is invoked only after the maximum number of retries. A downside to this method is that the state transition to "failed" cannot be interrupted, but this is not needed in this case and in most scenarios where you just want to do some cleanup after a job has failed.
NOTE: Empty catch handlers are bad, because they can hide bugs and make them hard to debug in production. It is necessary here, so the callback doesn't get called repeatedly forever. You may want to log exceptions for debugging purposes. It is also advisable to reduce the risk of exceptions in a job filter. One possibility is, instead of doing the cleanup work in-place, to schedule a new background job which runs if the original job failed. Be careful to not apply the filter CleanupAfterFailureFilter to it, though. Don't register it globally, or add some extra logic to it...
You can use OnPerforming or OnPerformed method of IServerFilter if you want to check the attempts or if you want you can just wait on OnStateElection of IElectStateFilter. I don't know exactly what requirement you have so it's up to you. Here's the code you want :)
public class JobStateFilter : JobFilterAttribute, IElectStateFilter, IServerFilter
{
public void OnStateElection(ElectStateContext context)
{
// all failed job after retry attempts comes here
var failedState = context.CandidateState as FailedState;
if (failedState == null) return;
}
public void OnPerforming(PerformingContext filterContext)
{
// do nothing
}
public void OnPerformed(PerformedContext filterContext)
{
// you have an option to move all code here on OnPerforming if you want.
var api = JobStorage.Current.GetMonitoringApi();
var job = api.JobDetails(filterContext.BackgroundJob.Id);
foreach(var history in job.History)
{
// check reason property and you will find a string with
// Retry attempt 3 of 3: The method or operation is not implemented.
}
}
}
How to add your filter
GlobalJobFilters.Filters.Add(new JobStateFilter());
----- or
var options = new BackgroundJobServerOptions
{
FilterProvider = new JobFilterCollection { new JobStateFilter() };
};
app.UseHangfireServer(options, storage);
Sample output :

SignalR - Detect disconnected client in no time

I am working on an application that needs to recognize when someone log's off from system.
I've set ping interval to 5 seconds. I also have public override Task OnConnected() and public override Task OnDisconnected(), and they are triggered each time client connects and disconnects (I remember clients names and connections while connecting, and remove those data from list when disconnected)
So, when a client log's off the system, his connection is lost and he doesn't send any ping response. I have this solution working, but when it takes too much time, around 30 seconds to run OnDisconnected function.
Is there any possibility to make this process faster? I have to detect this in at least 4-5 seconds.
EDIT: here is the code
Hub.cs:
public class SignalRConnection
{
public string ConnectionId { get; set; }
public string UserName { get; set; }
}
public static List<SignalRConnection> connections = new List<SignalRConnection>();
public override Task OnConnected()
{
connections.Add(new SignalRConnection() { ConnectionId = Context.ConnectionId, UserName=Context.User.Identity.Name});
return base.OnConnected();
}
public override Task OnDisconnected()
{
var forDelete = connections.FirstOrDefault(p => p.ConnectionId == Context.ConnectionId);
connections.Remove(forDelete);
Clients.All.logoffActions(forDelete.UserName);
return base.OnDisconnected();
}
Global.asax
GlobalHost.Configuration.ConnectionTimeout =TimeSpan.FromSeconds(6);
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(6);
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(2);
You can detect what happens from javascript. This will help understanding what happens with the connection: http://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events
Basically first, your connection goes in reconnecting state (can be slow connection, short interruption in connection ... ) In this state tries to connect again. By default 6 times every 5 seconds, which takes 30 seconds. If no success fires the disconnected event which is going to call your hub's OnDisconnected method.
You can use the reconnecting function in javascript, but in this state, client can still come back.
You can use something like this is JS:
var tryingToReconnect = false;
$.connection.hub.reconnecting(function() {
tryingToReconnect = true;
});
$.connection.hub.reconnected(function() {
tryingToReconnect = false;
});
$.connection.hub.disconnected(function() {
if(tryingToReconnect) {
notifyUserOfDisconnect(); // Your function to notify user.
}
});
When the connection is down $.connection.hub.reconnecting(function() { will be called instantly, (but the firing of this event doesn't always mean that the connection is down! It might just be a quick connection problem)
Another useful thing would be the connectionSlow event.
$.connection.hub.connectionSlow(function() {
notifyUserOfConnectionProblem(); // Your function to notify user.
});
Most importantly to understand the states and the transitions described in the linked description.
I hope it helps. Cheers!

How to remove item from ConcurrentDictionary after final ContinueWith finishes

First, could someone with 1500+ "reputation" please create a tag for "ContinueWith" (and tag this question with it)? Thanks!
Sorry for the length of this post but I don't want to waste the time of anyone trying to help me because I left out relevant details. That said, it may still happen. :)
Now the details. I am working on a service that subscribes to a couple of ActiveMQ queue topics. Two of the topics are somewhat related. One is a "company update" and one is a "product update". The "ID" for both is the CompanyID. The company topic includes the data in the product topic. Required because other subscribers need the product data but don't want/need to subscribe to the product topic. Since my service is multi-threaded (requirement beyond our discretion), as the messages arrive I add a Task to process each one in a ConcurrentDictionary using AddOrUpdate where the update parm is simply a ContinueWith (see below). Done to prevent simultaneous updates which could happen because these topics and subscribers are "durable" so if my listener service goes offline (whatever reason) we could end with multiple messages (company and/or product) for the same CompanyID.
Now, my actual question (finally!) After the Task (whether just one task, or the last in a chain of ContinueWith tasks) is finished, I want to remove it from the ConcurrentDictionary (obviously). How? I have thought of and gotten some ideas from coworkers but I don't really like any of them. I am not going to list the ideas because your answer might be one of those ideas I have but don't like but it may end up being the best one.
I have tried to compress the code snippet to prevent you from having to scroll up and down too much, unlike my description. :)
nrtq = Not Relevant To Question
public interface IMessage
{
long CompantId { get; set; }
void Process();
}
public class CompanyMessage : IMessage
{ //implementation, nrtq }
public class ProductMessage : IMessage
{ //implementation, nrtq }
public class Controller
{
private static ConcurrentDictionary<long, Task> _workers = new ConcurrentDictionary<long, Task>();
//other needed declarations, nrtq
public Controller(){//constructor stuff, nrtq }
public StartSubscribers()
{
//other code, nrtq
_companySubscriber.OnMessageReceived += HandleCompanyMsg;
_productSubscriber.OnMessageReceived += HandleProductMsg;
}
private void HandleCompanyMsg(string msg)
{
try {
//other code, nrtq
QueueItUp(new CompanyMessage(message));
} catch (Exception ex) { //other code, nrtq }
}
private void HandleProductMsg(string msg)
{
try {
//other code, nrtq
QueueItUp(new ProductMessage(message));
} catch (Exception ex) { //other code, nrtq }
}
private static void QueueItUp(IMessage message)
{
_workers.AddOrUpdate(message.CompanyId,
x => {
var task = new Task(message.Process);
task.Start();
return task;
},
(x, y) => y.ContinueWith((z) => message.Process())
);
}
Thanks!
I won't "Accept" this answer for a while because I am eager to see if anyone else can come up with a better solution.
A coworker came up with a solution which I tweaked a little bit. Yes, I am aware of the irony (?) of using the lock statement with a ConcurrentDictionary. I don't really have the time right now to see if there would be a better collection type to use. Basically, instead of just doing a ContinueWith() for existing tasks, we replace the task with itself plus another task tacked on the end using ContinueWith().
What difference does that make? Glad you asked! :) If we had just done a ContinueWith() then the !worker.Value.IsCompleted would return true as soon as the first task in the chain is completed. However, by replacing the task with two (or more) chained tasks, then as far as the collection is concerned, there is only one task and the !worker.Value.IsCompleted won't return true until all tasks in the chain are complete.
I admit I was a little concerned about replacing a task with itself+(new task) because what if the task happened to be running while it is being replaced. Well, I tested the living daylights out of this and did not run into any problems. I believe what is happening is that since task is running in its own thread and the collection is just holding a pointer to it, the running task is unaffected. By replacing it with itself+(new task) we maintain the pointer to the executing thread and get the "notification" when it is complete so that the next task can "continue" or the IsCompleted returns true.
Also, the way the "clean up" loop works, and where it is located, means that we will have "completed" tasks hanging around in the collection but only until the next time the "clean up" runs which is the next time a message is received. Again, I did a lot of testing to see if I could cause a memory problem due to this but my service never used more than 20 MB of RAM, even while processing hundreds of messages per second. We would have to receive some pretty big messages and have a lot of long running tasks for this to ever cause a problem but it is something to keep in mind as your situation may differ.
As above, in the code below, nrtq = not relevant to question.
public interface IMessage
{
long CompantId { get; set; }
void Process();
}
public class CompanyMessage : IMessage
{ //implementation, nrtq }
public class ProductMessage : IMessage
{ //implementation, nrtq }
public class Controller
{
private static ConcurrentDictionary<long, Task> _workers = new ConcurrentDictionary<long, Task>();
//other needed declarations, nrtq
public Controller(){//constructor stuff, nrtq }
public StartSubscribers()
{
//other code, nrtq
_companySubscriber.OnMessageReceived += HandleCompanyMsg;
_productSubscriber.OnMessageReceived += HandleProductMsg;
}
private void HandleCompanyMsg(string msg)
{
//other code, nrtq
QueueItUp(new CompanyMessage(message));
}
private void HandleProductMsg(string msg)
{
//other code, nrtq
QueueItUp(new ProductMessage(message));
}
private static void QueueItUp(IMessage message)
{
lock(_workers)
{
foreach (var worker in Workers)
{
if (!worker.Value.IsCompleted) continue;
Task task;
Workers.TryRemove(worker.Key, out task);
}
var id = message.CompanyId;
if (_workers.ContainsKey(id))
_workers[id] = _workers[id].ContinueWith(x => message.Process());
else
{
var task = new Task(y => message.Process(), id);
_workers.TryAdd(id, task);
task.Start();
}
}
}

java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#

I've read several related posts and even posted and answer here but it seems like I was not able to solve the problem.
I have 3 Activities:
Act1 (main)
Act2
Act3
When going back and forth Act1->Act2 and Act2->Act1 I get no issues
When going Act2->Act3 I get no issues
When going Act3->Act2 I get occasional crashes with the following error: java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#.... This is a ListView cursor.
What I tried:
1. Adding stopManagingCursor(currentCursor);to the onPause() of Act2 so I stop managing the cursor when leaving Act2 to Act3
protected void onPause()
{
Log.i(getClass().getName() + ".onPause", "Hi!");
super.onPause();
saveState();
//Make sure you get rid of the cursor when leaving to another Activity
//Prevents: ...Unable to resume activity... trying to requery an already closed cursor
Cursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
stopManagingCursor(currentCursor);
}
When returning back from Act3 to Act2 I do the following:
private void populateCompetitorsListView()
{
ListAdapter currentListAdapter = getListAdapter();
Cursor currentCursor = null;
Cursor tournamentStocksCursor = null;
if(currentListAdapter != null)
{
currentCursor = ((SimpleCursorAdapter)currentListAdapter).getCursor();
if(currentCursor != null)
{
//might be redundant, not sure
stopManagingCursor(currentCursor);
// Get all of the stocks from the database and create the item list
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
((SimpleCursorAdapter)currentListAdapter).changeCursor(tournamentStocksCursor);
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
startManagingCursor(tournamentStocksCursor);
//Create an array to specify the fields we want to display in the list (only name)
String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.COLUMN_SCORE};
// and an array of the fields we want to bind those fields to (in this case just name)
int[] to = new int[]{R.id.competitor_name, R.id.competitor_score};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to);
//tournamentStocks.convertToString(tournamentStocksCursor);
setListAdapter(tournamentStocks);
}
So I make sure I invalidate the cursor and use a different one. I found out that when I go Act3->Act2 the system will sometimes use the same cursor for the List View and sometimes it will have a different one.
This is hard to debug and I was never able to catch a crashing system while debugging. I suspect this has to do with the time it takes to debug (long) and the time it takes to run the app (much shorter, no pause due to breakpoints).
In Act2 I use the following Intent and expect no result:
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(this, ActivityCompetitorDetails.class);
intent.putExtra(StournamentConstants.App.competitorId, id);
intent.putExtra(StournamentConstants.App.tournamentId, mTournamentRowId);
startActivity(intent);
}
Moving Act1->Act2 Act2->Act1 never gives me trouble. There I use startActivityForResult(intent, ACTIVITY_EDIT); and I am not sure - could this be the source of my trouble?
I would be grateful if anyone could shed some light on this subject. I am interested in learning some more about this subject.
Thanks,D.
I call this a 2 dimensional problem: two things were responsible for this crash:
1. I used startManagingCursor(mItemCursor); where I shouldn't have.
2. I forgot to initCursorAdapter() (for autocomplete) on onResume()
//#SuppressWarnings("deprecation")
private void initCursorAdapter()
{
mItemCursor = mDbHelper.getCompetitorsCursor("");
startManagingCursor(mItemCursor); //<= this is bad!
mCursorAdapter = new CompetitorAdapter(getApplicationContext(), mItemCursor);
initItemFilter();
}
Now it seems to work fine. I hope so...
Put this it may work for you:
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
orderCursor.requery();
}
This also works
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
startManagingCursor(Cursor);
}

Resources