I have a recursive function in a windows service. This function upon completion rewinds itself as it has been repeated multiple times in recursion. Isn't that an overhead ?
Is there any way to avoid unwinding ? Is there any better approach?
Edit : In this method, I get 100 records from DB and then process them and then get another 100 and so on till all the records in DB have been processed.
Also, there is no limit of how many total records there might be in the db so this function can repeat itself quite a lot.
public void ServiceFunctionality()
{
try
{
// Get Data From WEBAPI
HttpClient client = new HttpClient();
HttpResponseMessage response = response = client.GetAsync("webapi url link").Result;
Response<ServiceWrapper> objResponse = response.Content.ReadAsAsync<Response<ServiceWrapper>>().Result;
if (objResponse != null)
{
if (objResponse.isSuccess == true)
{
listContact = objResponse.data.lContact;
int MaxPKinSelectedRecords = objResponse.data.MaxPKinSelectedRecords;
int MaxPKinTotalRecords = objResponse.data.MaxPKinTotalRecords;
if (listContact != null && listContact.Count>0)
{
try
{
Parallel.ForEach(listContact, contact =>
{
// some code...
});
// Recursive Call
if (MaxPKinTotalRecords != MaxPKinSelectedRecords)
{
ServiceFunctionality();
}
}
catch (Exception ex)
{
// Logging
}
}
}
else
{
// Logging
}
}
else
{
// Logging
}
}
catch (Exception ex)
{
// Logging
}
}
You can always unwind to a while loop. Because your calls aren't altering state, this is trival.
public void ServiceFunctionality()
{
bool done = false;
while(!done) {
try
{
done = true; //if we don't reset this, we're done.
// Get Data From WEBAPI
HttpClient client = new HttpClient();
HttpResponseMessage response = response = client.GetAsync("webapi url link").Result;
Response<ServiceWrapper> objResponse = response.Content.ReadAsAsync<Response<ServiceWrapper>>().Result;
if (objResponse != null)
{
if (objResponse.isSuccess == true)
{
listContact = objResponse.data.lContact;
int MaxPKinSelectedRecords = objResponse.data.MaxPKinSelectedRecords;
int MaxPKinTotalRecords = objResponse.data.MaxPKinTotalRecords;
if (listContact != null && listContact.Count>0)
{
try
{
Parallel.ForEach(listContact, contact =>
{
// some code...
});
// set loop variable
if (MaxPKinTotalRecords != MaxPKinSelectedRecords)
{
done = false;
}
}
catch (Exception ex)
{
// Logging
}
}
}
else
{
// Logging
}
}
else
{
// Logging
}
}
catch (Exception ex)
{
// Logging
}
}
}
Do not use recursion for calling a function whenever you have alternate suitable solution. I personally almost never do
I have tried to keep it same other than using a while..
Do not forget to break your loop. I tried to handle this thing but still
Just to be very careful, never take a risk of infinite loop on server I took maxPossibleIterations. So that in case of any mistake your web service server would not have to go for infinite iterations
public void ServiceFunctionality()
{
long maxPossibleIterations = 999999;
try
{
while (true)
{
maxPossibleIterations++;
// Get Data From WEBAPI
HttpClient client = new HttpClient();
HttpResponseMessage response = response = client.GetAsync("webapi url link").Result;
Response<ServiceWrapper> objResponse = response.Content.ReadAsAsync<Response<ServiceWrapper>>().Result;
if (objResponse != null)
{
if (objResponse.isSuccess == true)
{
listContact = objResponse.data.lContact;
int MaxPKinSelectedRecords = objResponse.data.MaxPKinSelectedRecords;
int MaxPKinTotalRecords = objResponse.data.MaxPKinTotalRecords;
if (listContact != null && listContact.Count>0)
{
try
{
Parallel.ForEach(listContact, contact =>
{
// some code...
});
if (MaxPKinTotalRecords == MaxPKinSelectedRecords)
{
break;
}
}
catch (Exception ex)
{
// Logging
}
}
else
break; //Important
}
else
{
// Logging
break;
}
}
else
{
// Logging
break;
}
} // End while
}
catch (Exception ex)
{
// Logging
}
}
Related
StackOverFlowExceprion raised, when logDirectory = new DirectoryInfo(m_logFileDirectory); line was executing. How can I solve the problem? Please help me.
This procedure writeLogToFile write a logMessge to File to logDirectory.
It is part of Log write program.
private void writeLogToFile(string logMessge)
{
DirectoryInfo logDirectory = null;
try
{
Monitor.Enter(m_lock);
logDirectory = new DirectoryInfo(m_logFileDirectory);
if (!logDirectory.Exists)
{
logDirectory.Create();
}
if (m_streamWriter == null) newLogFile();
if (m_logFileAutoSeperate && (m_streamWriter.BaseStream.Length > m_logFileSize * 1024))
{
newLogFile();
m_streamWriter.WriteLine(logMessge);
}
else
{
m_streamWriter.WriteLine(logMessge);
}
// stream writer uses internal buffer.
// if directWriting option is true, the file will be write(flush) once.
if (directWriting) m_streamWriter.Flush();
}
catch (StackOverflowException sofex)
{
AppExceptionHandler.writeException(sofex);
}
catch (AppException aex)
{
AppExceptionHandler.writeException(aex);
}
catch (Exception ex)
{
AppExceptionHandler.writeException(ex);
}
finally
{
Monitor.Exit(m_lock);
}
}
From the comments, this is what newLogFile looks like:
private void newLogFile()
{
try
{
Monitor.Enter(m_lock);
if (m_streamWriter != null)
{
endLogging();
m_streamWriter.Flush();
m_streamWriter.Close();
}
m_logFileNameSuffix = getLogFileNewSuffix();
m_streamWriter = File.AppendText(getLogFileName());
startLogging();
}
}
Hi guy's i'm trying to figure out a way to display a DisplayAlert Popup when Someone entered the Wrong details into the Login Process.
Issue is, The login's a little "Weird" I'm not comparing against a Database i'm comparing against a List of Customers I get from a APi So I have to loop threw to then find if the detail's are correct.
I have a login Phase 1() which Checks against the Wordpress API but I want to have this be able to notify on Phase 1 and 2, Phase 1 is a Username = Username Password = Password Where phase 2 is just a Username = Username , I know it's not secure The Login is more of a Formality then anything.
public async void Login_Phase1()
{
try
{
#region Login Phase 1
var client = new WordPressClient("http://XXX.co.za/wp-json/");
client.AuthMethod = AuthMethod.JWT;
try
{
await client.RequestJWToken(Usernamelabel.Text, Password.Text);
}
catch (Exception e)
{
await App.Current.MainPage.DisplayAlert("Something Went wrong", e.ToString(), "OK");
}
var x = client;
var isValidToken = await client.IsValidJWToken();
WpApiCredentials.token = client.GetToken();
if (isValidToken)
{
Login_Phase2();
}
else
{
await App.Current.MainPage.DisplayAlert("Detail's are Incorect", "Token not Found", "OK");
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
#endregion
}
public void Login_Phase2()
{
try
{
#region login Phase 2
var list = FetchCustomers.customers.ToList();
foreach (var user in list)
{
if (user.username == Usernamelabel.Text)
{
Preferences.Set("CId", user.id.ToString());
Preferences.Set("Token", WpApiCredentials.token);
Preferences.Set("CUsername", user.username);
Preferences.Set("CEmail", user.email);
Users.Loggedin = true;
Application.Current.SavePropertiesAsync();
App.Current.MainPage.DisplayAlert("Complete", "Login Process Complete, Enjoy", "OK");
App.Current.MainPage = new Home("Mica Market");
}
//Want to add a Display popup Here to say the information is entered incorrectly, but
not have it repeat 200 Time's
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
#endregion
}
Fetching all the Customers to check against
private async void ExtractWooData(List<Customer> x)
{
try
{
#region FetchC
RestAPI rest = new RestAPI("http://xxxxxx/wp-json/wc/v3/", "ck_a25xxxxxxxxxxx0", "cs_8xxxxxxxx8xxxx");
WCObject wc = new WCObject(rest);
int pageNum = 1;
var isNull = false;
List<Customer> oldlist;
while (!isNull)
{
var page = pageNum.ToString();
x = await wc.Customer.GetAll(new Dictionary<string, string>() {
{
"page", page
}, {
"per_page", "100"
}
});
oldlist = FetchCustomers.customers ?? new List<Customer>();
if (x.Count == 0)
{
break;
}
else
{
//1st loop customers needs to = 100
//2nd loop oldist needs to = 40+
//If count = 0 then => Combine Customers + Oldist
pageNum++;
FetchCustomers.customers = oldlist.Union(x).ToList();
}
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
#endregion
}
Any Advice?
you can replace the foreach with a LINQ query
// find the first match
var found = list.Where(user => user.username == Usernamelabel.Text).FirstOrDefault();
if (found != null)
{
// set preferences and navigation
}
else
{
// DisplayAlert
}
Using: Windows 10, C# .NET 2015 Community, UWP
Im trying to build a windows-universal-app that pairs my PC with a BLE device.
Whats already working is enumerating nearby devices, pair with a selected one and getting information like battery-level and firmware-revision.
The problem now is that when I try to get a custom service, my task ends because of an "System.Exception" at .GetGattService
System.Exception.Message: "Element not found. (Exception from HRESULT: 0x80070490)"
System.Exception.Stack : "at Windows.Devices.Bluetooth.BluetoothLEDevice.GetGattService(Guid serviceUuid)\r\n at SettingsCs.Settings.d__23.MoveNext()"
This is the code that's not working:
private async Task<SettingsReturn> writeSettingTransition(BluetoothLEDevice device, byte[] byteSettings)
{
//Check if device is available
if (device != null)
{
Guid SERVICE_CUSTOM = new Guid("7e0bc6be-8271-4f5a-a126-c24220e6250c");
GattDeviceService service = device.GetGattService(SERVICE_CUSTOM);
//Check if service is available
if (service == null)
{
return SettingsReturn.INIT_ERROR;
}
GattCharacteristic characteristic = service.GetCharacteristics(BLETestApp.CHAR_SETTINGS)[0];
//Check if characteristic is available
if (characteristic == null)
{
return SettingsReturn.INIT_ERROR;
}
var writer = new DataWriter();
writer.WriteBytes(byteSettings);
var buffer = writer.DetachBuffer();
await characteristic.WriteValueAsync(buffer);//********
bool success = characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Write);
if (success == true)
{
// Take care of the 8 bit byte for the counter (max = 255 (unsigned))
if (TRANSACTION_ID > 250)
{
TRANSACTION_ID = 0;
}
else
{
// Count TANSACTION_ID one up
TRANSACTION_ID++;
}
return SettingsReturn.OK;
}
else
{
return SettingsReturn.WRITE_ERROR;
}
}
else
{
return SettingsReturn.INIT_ERROR;
}
}
I hope somenone can help me or tell me what I'm doing wrong.
I can't pinpoint the error you get, use the debugger to check if your characteristic has write permission.
I have changed your code in a way I write to my device successfully.
Also added a try catch block.
Here it is:
private async Task<SettingsReturn> writeSettingTransition(BluetoothLEDevice device, byte[] byteSettings)
{
bool success = false;
//Check if device is available
if (device != null)
{
Guid SERVICE_CUSTOM = new Guid("7e0bc6be-8271-4f5a-a126-c24220e6250c");
GattDeviceService service = device.GetGattService(SERVICE_CUSTOM);
//Check if service is available
if (service == null)
{
return SettingsReturn.INIT_ERROR;
}
GattCharacteristic characteristic = service.GetCharacteristics(BLETestApp.CHAR_SETTINGS)[0];
//Check if characteristic is available
if (characteristic == null)
{
return SettingsReturn.INIT_ERROR;
}
IBuffer writeBuffer = byteSettings.AsBuffer();// using Windows.Storage.Streams
try
{
// BT_Code: Writes the value from the buffer to the characteristic.
var result = await characteristic.WriteValueAsync(writeBuffer);
if (result == GattCommunicationStatus.Success)
{
// NotifyUser("Successfully wrote value to device" );
success = true;
}
else
{
// NotifyUser($"Write failed: {result}");
success = false;
}
}
catch (Exception ex) when ((uint)ex.HResult == 0x80650003 || (uint)ex.HResult == 0x80070005)
{
// E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED or E_ACCESSDENIED
// This usually happens when a device reports that it support writing, but it actually doesn't.
// NotifyUser(ex.Message, NotifyType.ErrorMessage);
}
if (success)
{
// Take care of the 8 bit byte for the counter (max = 255 (unsigned))
if (TRANSACTION_ID > 250)
{
TRANSACTION_ID = 0;
}
else
{
// Count TANSACTION_ID one up
TRANSACTION_ID++;
}
return SettingsReturn.OK;
}
else
{
return SettingsReturn.WRITE_ERROR;
}
}
else
{
return SettingsReturn.INIT_ERROR;
}
}
There can be typos and other mishaps, hope it helps.
This is killing me. I'm new to android/Xamarin. I can't find anything on the web that explains what is going on here.
I'm using xamarin forms for my application. I have a page that synchronizes the device with a web service.
The method simply retrieves 100 records at a time from the web service and updates a sqlite table on the device. I randomly get this error. I'm running 5000 records for my test sample.
Here is the button click:
public async void OnSyncCachedData_Clicked(object sender, EventArgs e)
{
activityIndicatorAll.IsRunning = true;
try
{
actIndSyncItems.IsRunning = true;
SyncAllFinished += SynchAllFinishedProcessing;
await Task.Run(async () => await App.ItemsRepo.LoadCacheDataFromCacheAsync(DbPath).ConfigureAwait(false));
}
catch (BAL.Exceptions.NetworkException nex)
{
await DisplayAlert(Messages.TitleError, nex.Message, Messages.MsgOk);
}
catch (Exception ex)
{
await DisplayAlert(Messages.TitleError, string.Format(Messages.MsgAreYouConnectedParm1, ex.Message), Messages.MsgOk);
}
finally
{
EventHandler handler = SyncAllFinished;
if (handler != null)
{
handler(this, new EventArgs());
}
SyncAllFinished -= SynchAllFinishedProcessing;
}
}
the main worker method:
public async Task<bool> LoadCacheDataFromCacheAsync(string dbPath)
{
WebSvcManagers.ItemsManager itemsWebServiceManager = new WebSvcManagers.ItemsManager();
List<Models.WebServiceItems> consumedRecords = new List<Models.WebServiceItems>() { };
int bufferSize = 100;
Log.Debug(TAG, "LoadCacheDataFromCacheAsync starting");
try
{
{
int lastID = 0;
IEnumerable<Models.WebServiceItems> remoteRecords = await BAL.DataAccessHelper.GetItemsFromGPCacheAsync(App.Login, lastID, bufferSize, itemsWebServiceManager).ConfigureAwait(false);
while (remoteRecords.Count() != 0)
{
foreach (Models.WebServiceItems remoteItem in remoteRecords)
{
// DbActionTypes dbAction = (DbActionTypes)remoteItem.DbAction;
Models.Items itemRecord = new Models.Items() { ItemNumber = remoteItem.ItemNumber.ToUpper().Trim(), Description = remoteItem.Description.Trim() };
Log.Debug(TAG, "Processing {0}", remoteItem.ItemNumber.Trim());
bool success = await AddRecordAsync(itemRecord).ConfigureAwait(false);
if (success)
consumedRecords.Add(remoteItem);
}
lastID = remoteRecords.Max(r => r.RecordID) + 1;
remoteRecords = await BAL.DataAccessHelper.GetItemsFromGPCacheAsync(App.Login, lastID, bufferSize, itemsWebServiceManager).ConfigureAwait(false);
}
}
// await UpdateConsumedRecords(consumedRecords).ConfigureAwait(false);
return true;
}
catch (Exception ex)
{
this.StatusMessage = ex.Message;
Log.Debug(TAG, "Error Catch: {0}", StatusMessage);
return false;
}
finally
{
itemsWebServiceManager = null;
HandleSyncFinished(this, new EventArgs());
SyncAllFinished -= HandleSyncFinished;
}
}
My simple webservice manager:
public static async Task<IEnumerable<Models.WebServiceItems>> GetItemsFromGPCacheAsync(Models.Login login, int offset, int bufferCount, WebSvcManagers.ItemsManager manager)
{
try
{
return await manager.GetCacheRecordsAsync(login, offset, bufferCount).ConfigureAwait(false);
}
catch (Exception)
{
throw;
}
}
And the code for the interaction with the web service:
const int bufferSize = 100;
public async Task<IEnumerable<Models.WebServiceItems>> GetCacheRecordsAsync(Models.Login login, int offSet, int bufferCount)
{
string deviceID = App.ConfigSettings.DeviceID.ToString("D");
try
{
///* Testing start */
//return await DataStore(bufferCount, offSet).ConfigureAwait(false);
///* Testing end */
if (!App.IsConnected)
throw new BAL.Exceptions.NetworkException(Messages.ExceptionNetworkConnection);
string user = login.UserName;
string password = login.Password;
HttpClient client = HttpClientExtensions.CreateHttpClient(user, password);
try
{
List<Models.WebServiceItems> items = new List<Models.WebServiceItems>() { };
int lastID = offSet;
int i = 0;
string uri = string.Format("{0}", string.Format(Messages.WebRequestItemsCacheParms3, deviceID, lastID, Math.Min(bufferCount, bufferSize)));
Log.Debug(TAG, string.Format("Webservice {0}", uri));
string response = await client.GetStringAsync(uri).ConfigureAwait(false);
while (i < bufferCount && response != null && response != "[]")
{
while (response != null && response != "[]")
{
dynamic array = JsonConvert.DeserializeObject(response);
foreach (var item in array)
{
i++;
items.Add(new Models.WebServiceItems()
{
ItemNumber = item["ITEMNMBR"].Value.Trim(),
Description = item["ITEMDESC"].Value.Trim(),
DbAction = (int)(item["DbAction"].Value),
RecordID = (int)(item["DEX_ROW_ID"].Value),
});
lastID = (int)(item["DEX_ROW_ID"].Value);
Log.Debug(TAG, string.Format("Webservice {0}", item["ITEMNMBR"].Value.Trim()));
}
if (i < Math.Min(bufferCount, bufferSize))
{
uri = string.Format("{0}", string.Format(Messages.WebRequestItemsCacheParms3, deviceID, lastID + 1, Math.Min(bufferCount, bufferSize)));
Log.Debug(TAG, string.Format("Webservice {0}", uri));
response = await client.GetStringAsync(uri).ConfigureAwait(false);
}
else
break;
}
}
Log.Debug(TAG, string.Format("Webservice return {0} items", items.Count()));
return items;
}
catch (Exception ex)
{
Log.Debug(TAG, "Error Catch: {0}", ex.Message);
throw ex;
}
}
catch (System.Net.Http.HttpRequestException nex)
{
throw new Exception(string.Format(Messages.ExceptionWebServiceLoginParm1, nex.Message));
}
catch (Exception)
{
throw;
}
}
I've had assistance from a Xamarin instructor and we thought we got it, (because this is random), but it clearly is not swatted. I've been hitting my head up against a wall for over 3 weeks on this. It smells like a memory leak, but I have no idea how to find it with such a generic error message that doesn't appear on web searches.
Somebody out there with some major brains, Please help!
Error:
08-03 12:41:11.281 D/X:ItemsRepositiory(16980): UpdateRecordAsync 65702-40710
08-03 12:41:11.306 D/X:ItemsManager(16980): Webservice DeleteCacheRecordAsync 20497
08-03 12:41:11.406 D/X:ItemsManager(16980): Webservice api/InventoryItems?DeviceID=7c5bb45d-2ea0-45b9-ae50-92f2e25a2983&OffSet=20498&Max=100&cached=true
Thread finished: <Thread Pool> #7 08-03 12:41:11.521 E/art (16980): Nested signal detected - original signal being reported The thread 'Unknown' (0x7) has exited with code 0 (0x0).
This might be a problem with the VS Android Emulator. As we have shown in tests, this is not reproducible on the Google Android Emulators, nor on Xamarin Android Player, nor on a physical Android device.
I have a server-client environment, where the client connects and synchronizes data with the server every 5 second.
For synchronizing I use a background thread on the client which works fine, but on one specific hardware the method GetNetworkAvailable throws out of memory exceptions occasionaly. The errors occur whitout logic, so I guess somethings just not good with this hardware. Anyways I'd like to get your opinion on my background - polling function.
private void SynchronizedWorker()
{
bool initialization = true;
int initializationTries = 0;
// Sync loop
while (!_shouldStop)
{
// Initialize locals
int syncInterval = _syncInterval; // Reset Sync Interval to default
SyncStatus syncStatus = SyncStatus; // Get current Status
bool hasNetworkConnection = true; // Has Network connection
try
{
//*******************************************
// Check Network connection
//*******************************************
if (!NetworkInterface.GetIsNetworkAvailable())
{
hasNetworkConnection = false;
_syncResetEvent.Set();
syncStatus = SyncStatus.Offline;
}
else if (syncStatus == SyncStatus.Offline) // Is in offline - State, but Network available again recognize going online
{
_syncResetEvent.Set();
hasNetworkConnection = IsServiceAvailable();
// Sync-Status stays offline
if (!hasNetworkConnection)
{
// Wait 1 minute, before retry
syncInterval = 60000;
}
}
//*******************************************
// Proceed with Syncronisation
//*******************************************
if (hasNetworkConnection)
{
syncStatus = SyncStatus.Ok;
// Try Initialization
if (initialization)
{
try
{
// Sync initialization here...
// ..............................
////////////////////////////////////
}
catch (Exception ex)
{
log.LogError(string.Format("Initialization Try {0}", initializationTries), ex);
syncStatus = SyncStatus.InitializationFailed;
}
}
// To many Init-Tries --> Stop
if (initializationTries > 1)
{
// Proceed
_syncResetEvent.Set();
_syncStatus = syncStatus;
break; // Stop Synch
}
// Debug
var sw = System.Diagnostics.Stopwatch.StartNew();
// Do Up/Download
if (!initialization)
{
try
{
// Synchronisation with service here...
// ..............................
////////////////////////////////////
// Proceed
_syncResetEvent.Set();
}
catch (Exception ex)
{
log.LogError("Download", ex);
syncStatus = SyncStatus.SynchFailed;
}
}
}
// Set Sync status
_syncStatus = syncStatus;
}
catch (Exception ex)
{
log.LogError("Sync-Worker", ex);
_syncStatus = Core.Sync.SyncStatus.SynchFailed;
// Proceed
_syncResetEvent.Set();
// Reset Force
_syncForce = false;
}
finally
{
// Set Completed
if (OnSyncCompleted != null)
{
OnSyncCompleted(downloaded, uploaded, executed);
}
// Always Wait for Interval
DateTime sleepuntil = DateTime.Now.AddMilliseconds(syncInterval);
while (sleepuntil > DateTime.Now && !_shouldStop && !_syncForce)
{
// Sleep
Thread.Sleep(100);
}
}
}
// Stop
_syncStatus = SyncStatus.Unknown;
}