How to run a timer in background in xamarin forms? - xamarin

In my app I want to set a timer to calculate the working time. My timer is working fine but when I switch to another page then it stops working. How to run the timer and calculate total time run in the background. Here is my code
Stopwatch st = new Stopwatch();
private void WorkClockStart(object sender,EventArgs e)
{
if(LaborClock.Text == "Start Work Clock")
{
LaborClock.Text = "Stop Work Clock";
Device.StartTimer(TimeSpan.FromMilliseconds(1), () =>
{
st.Start();
return false;
});
}
else
{
st.Stop();
long elapsed = st.ElapsedMilliseconds;
var sec = elapsed / 1000;
DisplayAlert("Message", "Worked Time(Sec): " + sec, "ok");
LaborClock.Text = "Start Work Clock";
st.Reset();
}
}
How to achieve this in Xamarin.Forms?

Why do you use a timer? Just store the DateTime.Now in a variable when you start your watch and compute the delta with DateTime.Now when you stop it.
Then you can store wherever you want (in a static variable for example or in App.cs if you want depending on your requirement)

I agree with Daniel you can use DateTime and Task.Factory.StartNew, Like the below code.
Task.Factory.StartNew( async() =>
{
var time = DateTime.Now;
var counter = 30;
transactionItem.RetryCount = 30;
do
{
await Task.Delay(1000);
counter = Math.Abs((DateTime.Now - time.AddSeconds(29)).Seconds);
} while (counter != 0 && time.AddSeconds(29) > DateTime.Now);
});

Related

Google appscript - if else statement not working in for loop

Trying to run the else statement in below code but cant make it work.
What am i missing here?
var startTime= (new Date()).getTime(); //code execution start time
function createtrigger() {
var currTime = (new Date()).getTime(); //current time
Logger.log((currTime-startTime)) //show time difference between start time and current time
//check if difference between current time and start time is greater than 0 is greater than starttime
if (currTime-startTime > 0 ) {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
//check if trigger function name is "createtrigger"
if (triggers[i].getHandlerFunction() == "createtrigger") {
console.log("Trigger already exists. Hence not created");
}
//if trigger function name is not "createtrigger" then create the trigger
else
ScriptApp.newTrigger("createtrigger")
.timeBased()
.everyMinutes(1)
.create();
console.log("Trigger created");
}
}
}
var startTime= (new Date()).getTime(); //code execution start time
function createtrigger() {
var currTime = (new Date()).getTime(); //current time
Logger.log((currTime-startTime)) //show time difference between start time and current time
//check if difference between current time and start time is greater than 0 is greater than starttime
if (currTime-startTime > 0 ) {
var triggers = ScriptApp.getProjectTriggers();
Logger.log(triggers);
if (triggers.length>0){
for (var i = 0; i < triggers.length; i++) {
//check if trigger function name is "createtrigger"
if (triggers[i].getHandlerFunction() == "createtrigger") {
Logger.log("Trigger already exists. Hence not created");
break;
}
//if trigger function name "createtrigger" was not found then create the trigger
if (i==triggers.length) {
ScriptApp.newTrigger("createtrigger")
.timeBased()
.everyMinutes(1)
.create();
Logger.log("Trigger created");
}
}
} else {
ScriptApp.newTrigger("createtrigger")
.timeBased()
.everyMinutes(1)
.create();
Logger.log("Trigger created first time");
}
}
}

what is the faster and best way to make a few million SOAP requests and save the results into SqlDb

I have a million records in my table. I want to call a soap service and i need to do process in all the records in less than one hour. and besides i should update my table , insert the requests and responses in my other tables. but the code below works on less than 10 records every time i run my app.
I know My code is wrong,, I want to know what is the best way to do it.
static async Task Send( )
{
var results = new ConcurrentDictionary<string, int>();
using (AppDbContext entities = new AppDbContext())
{
var List = entities.Request.Where(x => x.State == RequestState.InitialState).ToList();
Parallel.ForEach(Enumerable.Range(0, List.Count), async index =>
{
var selected = List.FirstOrDefault();
List.Remove( selected );
var res1 = await DoAsyncJob1(selected); ///await
// var res = CallService(selected);
var res2 = await DoAsyncJob2(selected); ///await
var res3 = await DoAsyncJob3(selected); ///await
// var responses = await Task.WhenAll(DoAsyncJob1, DoAsyncJob2, DoAsyncJob3);
// results.TryAdd(index.ToString(), res);
});
}
}
static async Task<int> DoAsyncJob1(Request item)
{
using (AppDbContext entities = new AppDbContext())
{
var bReq = new BankRequest();
bReq.Amount = Convert.ToDecimal(item.Amount);
bReq.CreatedAt = DateTime.Now;
bReq.DIBAN = item.DIBAN;
bReq.SIBAN = item.SIBAN;
entities.BankRequest.Add(bReq);
entities.SaveChanges();
}
return item.Id;
}
static async Task<int> DoAsyncJob2(Request item)
{
using (AppDbContext entities = new AppDbContext())
{
}
return item.Id;
}
static async Task<int> DoAsyncJob3(Request item)
{
using (AppDbContext entities = new AppDbContext())
{
}
return item.Id;
}
Maybe the below lines are wrong :
var selected = List.FirstOrDefault();
List.Remove( selected );
Thanks in advance..
First, it is a bad practice to use async-await within Parallel.For - you introduce only more load to the task scheduler and more overhead.
Second, you are right:
var selected = List.FirstOrDefault();
List.Remove( selected );
is very, very wrong. Your code will behave in a totally unpredictable way, due to the race conditions.

Oxyplot in xamarin not generated

I ran in to an issue in generating oxyplot with dynamic data. This is the first time I'm using oxyplot with dynamic data.
public async Task<PlotModel> AreaChart_NoOfPoliciesAsync()
{
var plotModel1 = new PlotModel { Title = "Number of Policies with last year" };
plotModel1.InvalidatePlot(true);
try
{
var s1 = new AreaSeries()
{
Title = "Number of policies in last year",
Color = OxyColors.LightPink,
MarkerType = MarkerType.Circle,
MarkerSize = 6,
MarkerStroke = OxyColors.White,
MarkerFill = OxyColors.LightPink,
MarkerStrokeThickness = 1.5
};
string year_str = DateTime.Today.AddYears(-1).ToString("yyyy");
int running_month = 1;
string running_month_str;
List<MonthlyPerformance> last_year = await _apiServices.GetMonthlyPerformance(Settings.AccessToken, Settings.agentCode, year_str);
last_year = last_year.FindAll(x => x.BUSS_TYPE == "Total");
last_year.Sort((x, y) => x.Y_MONTH.CompareTo(y.Y_MONTH));
s1.Points.Add(new DataPoint(0, 0));
foreach (MonthlyPerformance item in last_year)
{
s1.Points.Add(new DataPoint(running_month, item.NO_BUSINESS));
running_month++;
}
plotModel1.Series.Add(s1);
plotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Left, IsPanEnabled = false, IsZoomEnabled = false });
plotModel1.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, IsPanEnabled = false, IsZoomEnabled = false });
return plotModel1;}
The plot generated with hard coded values used for demo. But when the function
List<MonthlyPerformance> last_year = await _apiServices.GetMonthlyPerformance(Settings.AccessToken, Settings.agentCode, year_str);
is called, oxyplot is not being generated. I just get a blank space. I dont get any compilation errors.
I'm using MVVM. Could someone please point out what I'm doing wrong here.
Thanks in advance.
Once await and async were removed, the chart appeared.
I don't think it's the right way to handled the issue. But I was running out of development time.

General solution for ajax request in Protractor

I want to wait until ajax call complete. Below I wrote general method. But It seems that is not work.
When I ran call function every afterajax request , isLoaded always to be true.
In protractor, Is there any solution? Or where have I made mistake?
Thank you
module.waitUntilJqueryLoad = async function (timeout) {
var isDone = false;
timeout = timeout || 60;
await browser.sleep(1000);
//Wait for jQuery to load
var isLoaded = await browser.driver.executeScript("return jQuery.active == 0;");
if(isLoaded) {
console.log("JQuery is Ready!");
return await browser;
}
//This loop will rotate for 60 times to check If page Is ready after every 1 second.
//You can replace your value with 60 If you wants to Increase or decrease wait time.
for (var i = 0; i < timeout; i++) {
try {
await browser.sleep(1000);
} catch (err) {}
//To check page ready state.
var isLoaded = await browser.driver.executeScript("return jQuery.active == 0;");
console.log(isLoaded);
if(isLoaded) {
console.log("JQuery is Ready");
isDone = true;
} else {
console.log("JQuery is NOT Ready !!");
}
if(isDone)
break;
}
return browser;
};
I have a work around for that. If your loading popup added display style, it will work.
This is not a general solution but other posted solution has not worked even below code.
await browser.wait(until.invisibilityOf(element(by.id('loadingPanel'))), 60000);
Example Usage :
element(by.id('selectPerson')).waitForInvisibilityOf(10000); // wait 10 seconds
Here is my solution;
protractor.ElementFinder.prototype.waitForInvisibilityOf = async function (timeout) {
var _debug = true;
var isDone = false;
timeout = timeout || 60000;
var seconds = timeout / 1000;
if(await !this.isPresent())
return this;
//This loop will rotate for 60 times to check If page Is ready after every 1 second.
//You can replace your value with 60 If you wants to Increase or decrease wait time.
for (var i = 1; i <= seconds; i++) {
await browser.sleep(1000);
var style = await this.getAttribute('style');
var insibilityOf = await style.includes('display: none;');
var visibilityOf = await style.includes('display: block;');
if(insibilityOf) {
if(_debug)
console.log(i + " second: Element invisible!");
isDone = true;
}
else {
if(_debug)
console.log(i + " second: Element NOT invisible!");
}
if(seconds === i)
throw "Element invisibility timed out after "+ timeout +" milliseconds";
if(!insibilityOf && !visibilityOf && i > 10) // break for paging is loaded
break;
if(isDone) // If element is invisible
break;
}
return await this; };

Windows phone 8 gps / altitude problems

UPDATE: using the sample from here - http://code.msdn.microsoft.com/wpapps/Location-sample-f11aa4e7 and adding an altitude readout I get the same thing as my code. Poor accuracy is being off by 50ft. Going back and forth between 720 (correct) and 300 ft means something is wrong. I just can't see where...
I'm starting to make a GPS tracking app for windows phone 8 but something is going haywire. In my app, (and in the sample location app) i get some readings that are correct and others that are not. In general, the altitude jumps back and forth between ~95 and ~215 (with 215 being correct). The distance I'm getting is hugely inaccurate as well, quickly jumping to several miles while sitting at my desk or walking around outside.
I'm not sure what code to post, as it is identical to the sample code. If you think there is another relevant section i should post let me know and I'll add it.
double maxSpeed = 0.0;
double maxAlt = -9999999.0;
double minAlt = 9999999.0;
double curDistance = 0.0;
GeoCoordinate lastCoord = null;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if ((bool)IsolatedStorageSettings.ApplicationSettings["LocationConsent"] != true)
{
// The user has opted out of Location.
return;
}
if (App.Geolocator == null)
{
// Use the app's global Geolocator variable
App.Geolocator = new Geolocator();
}
App.Geolocator.DesiredAccuracy = PositionAccuracy.High;
//App.Geolocator.MovementThreshold = 1; // The units are meters.
App.Geolocator.ReportInterval = 1000;
//App.Geolocator.DesiredAccuracyInMeters = 50;
App.Geolocator.StatusChanged += geolocator_StatusChanged;
App.Geolocator.PositionChanged += geolocator_PositionChanged;
/*
geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
//geolocator.MovementThreshold = 1; // The units are meters.
geolocator.ReportInterval = 1000;
geolocator.StatusChanged += geolocator_StatusChanged;
geolocator.PositionChanged += geolocator_PositionChanged;
*
* */
logging = true;
startTime = DateTime.Now;
}
public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
{
return new GeoCoordinate
(
geocoordinate.Latitude,
geocoordinate.Longitude,
geocoordinate.Altitude ?? Double.NaN,
geocoordinate.Accuracy,
geocoordinate.AltitudeAccuracy ?? Double.NaN,
geocoordinate.Speed ?? Double.NaN,
geocoordinate.Heading ?? Double.NaN
);
}
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
Dispatcher.BeginInvoke(() =>
{
if (lastCoord == null)
{
lastCoord = ConvertGeocoordinate(args.Position.Coordinate);
}
DateTime currentTime = DateTime.Now;
TimeSpan totalTime = currentTime - startTime;
timeValue.Text = totalTime.ToString(#"hh\:mm\:ss");
System.Diagnostics.Debug.WriteLine(args.Position.Coordinate.Altitude.ToString());
GeoCoordinate thisLocation = ConvertGeocoordinate(args.Position.Coordinate);
if (true) //units check true = standard
{
double speed = (double)thisLocation.Speed;
speed *= 2.23694; //m/s -> mph
speedValue.Text = speed.ToString("0");
double alt = (double)thisLocation.Altitude;
if (alt > maxAlt)
{
maxAlt = alt;
}
if (alt < minAlt)
{
minAlt = alt;
}
/*
double currentAlt = (maxAlt - minAlt);
currentAlt *= 3.28084; //m -> ft
* */
alt *= 3.28084;
altValue.Text = alt.ToString("0");
double distance = thisLocation.GetDistanceTo(lastCoord);
curDistance += distance;
distance = curDistance * 0.000621371; // m -> miles
distanceValue.Text = distance.ToString("0.00");
distanceUnits.Text = "(mi)";
speedUnits.Text = "(mph)";
altUnits.Text = "(ft)";
}
});
}
EDIT: I didn't mention, but the speed is perfectly fine as an fyi. the lat / long is pretty close in general to where i am as well, so I don't think it's a hardware issue.
UPDATE: When stopping in the debugger to check the value instead of just printing it, it gives this:
Altitude = An internal error has occurred while evaluating method Windows.Devices.Geolocation.Geocoordinate.get_Altitude()
I tried to search for this, but the error is nowhere to be found on the internet...
The documentation states that altitude and a few others aren't guaranteed, but it also says that the value will be null if it isn't there. I check, and it's never null. It always prints a value, either correct or ~400 ft off.
UPDATE: Sample code:
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
System.Diagnostics.Debug.WriteLine(args.Position.Coordinate.Altitude.ToString());
if (!App.RunningInBackground)
{
Dispatcher.BeginInvoke(() =>
{
LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00");
LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00");
});
}
else
{
Microsoft.Phone.Shell.ShellToast toast = new Microsoft.Phone.Shell.ShellToast();
toast.Content = args.Position.Coordinate.Latitude.ToString("0.00");
toast.Title = "Location: ";
toast.NavigationUri = new Uri("/MainPage.xaml", UriKind.Relative);
toast.Show();
}
}
You might be seeing a different issues (too) but GPS altitudes are not very reliable. I have a few Garmin devices and they all jump about all over the place. You really need a barometer for decent altitude accuracy.
Here is a link on GPS attitude inaccuracy GPS Elevation

Resources