/// <summary> /// Thread safe /// </summary> /// <returns></returns> public static async Task <List <AccountDataItem> > GetAllAccounts() { List <AccountDataItem> accounts = new List <AccountDataItem>(); IList <IFolder> folders; folders = await System.Threading.Tasks.Task.Run(async delegate { using (await Locks.LockAccounts()) { return(await FileHelper.GetAllAccountFolders()); } }); foreach (IFolder accountFolder in folders) { if (Guid.TryParse(accountFolder.Name, out Guid localAccountId)) { AccountDataItem account = await AccountsManager.GetOrLoad(localAccountId); if (account != null) { accounts.Add(account); } } } return(accounts); }
/// <summary> /// Thread safe, but will lock the thread /// </summary> /// <param name="localAccountId"></param> /// <returns></returns> public static async Task Delete(Guid localAccountId) { await Task.Run(async delegate { using (await Locks.LockAccounts()) { using (await Locks.LockDataForWriteAsync("AccountsManager.Delete")) { IFolder accountFolder = await FileHelper.GetAccountFolder(localAccountId); if (accountFolder != null) { AccountDataStore.Dispose(localAccountId); try { await accountFolder.DeleteAsync(); } catch { } } } _cachedAccounts.Remove(localAccountId); } }); if (OnAccountDeleted != null) { OnAccountDeleted(null, localAccountId); } // Clear reminders try { RemindersExtension.Current?.ClearReminders(localAccountId); } catch { } // Clear calendar integration try { if (AppointmentsExtension.Current != null) { await AppointmentsExtension.Current.DeleteAsync(localAccountId); } } catch { } // Unpin tiles try { TilesExtension.Current?.UnpinAllTilesForAccount(localAccountId); } catch { } }
/// <summary> /// Thread safe, runs on own thread for data lock. /// </summary> /// <param name="account"></param> /// <returns></returns> public static async Task Save(AccountDataItem account) { using (MemoryStream stream = new MemoryStream()) { // Serialize on current thread GetSerializer().WriteObject(stream, account); stream.Position = 0; await Task.Run(async delegate { using (await Locks.LockAccounts()) { // Get the account folder var timeTracker = TimeTracker.Start(); IFolder accountFolder = await FileHelper.GetOrCreateAccountFolder(account.LocalAccountId); timeTracker.End(3, "AccountsManager.Save GetOrCreateAccountFolder"); // Create a temp file to write to timeTracker = TimeTracker.Start(); IFile tempAccountFile = await accountFolder.CreateFileAsync("TempAccountData.dat", CreationCollisionOption.ReplaceExisting); timeTracker.End(3, "AccountsManager.Save creating temp file"); // Write the data to the temp file timeTracker = TimeTracker.Start(); using (Stream s = await tempAccountFile.OpenAsync(StorageEverywhere.FileAccess.ReadAndWrite)) { timeTracker.End(3, "AccountsManager.Save opening file stream"); timeTracker = TimeTracker.Start(); stream.CopyTo(s); timeTracker.End(3, "AccountsManager.Save copying stream to file"); } // Move the temp file to the actual file timeTracker = TimeTracker.Start(); await tempAccountFile.RenameAsync(FileNames.ACCOUNT_FILE_NAME, NameCollisionOption.ReplaceExisting); timeTracker.End(3, "AccountsManager.Save renaming temp file to final"); } }); } }
private static async Task <AccountDataItem> GetOrLoadHelper(Guid localAccountId) { Debug.WriteLine("GetOrLoad Account: " + localAccountId); CachedAccountEntry entry; lock (_cachedAccounts) { if (!_cachedAccounts.TryGetValue(localAccountId, out entry)) { entry = new CachedAccountEntry(); _cachedAccounts[localAccountId] = entry; } // Cache entry exists else { // But account still might have been disposed var account = entry.Account; if (account != null) { Debug.WriteLine("Returning cached account: " + localAccountId); return(account); } } } Debug.WriteLine("GetOrLoad Account starting thread to enter data lock: " + localAccountId); // We'll have to enter a lock and then load it (if it's not already loaded at that point) return(await System.Threading.Tasks.Task.Run(async delegate { Debug.WriteLine("GetOrLoad Account acquiring lock: " + localAccountId); using (await Locks.LockAccounts()) { Debug.WriteLine("GetOrLoad Account acquired lock: " + localAccountId); AccountDataItem account; // Double check if account's already loaded (might have been loaded by the time we've entered the lock) account = entry.Account; if (account != null) { Debug.WriteLine("GetOrLoad Account, account already loaded: " + localAccountId); return account; } Debug.WriteLine("Loading account: " + localAccountId); account = await Load(localAccountId); // If account doesn't exist if (account == null) { Debug.WriteLine("Account didn't exist: " + localAccountId); return null; } Debug.WriteLine("Loaded account: " + localAccountId); entry.Account = account; return account; } })); }