public async Task LoadFoldersAsync(Config config, SystemInfo systemInfo, CancellationToken cancellationToken)
        {
            // If the folder is invalid for any reason, we'll ignore it.
            // Again, there's the potential for duplicate folder IDs (if the user's been fiddling their config). 
            // In this case, there's nothing really sensible we can do. Just pick one of them :)
            var folderConstructionTasks = config.Folders
                .Where(x => String.IsNullOrWhiteSpace(x.Invalid))
                .DistinctBy(x => x.ID)
                .Select(async folder =>
                {
                    var ignores = await this.FetchFolderIgnoresAsync(folder.ID, cancellationToken);
                    var syncState = await this.FetchFolderSyncStateAsync(folder.ID, cancellationToken);
                    var path = folder.Path;
                    if (path.StartsWith("~"))
                        path = Path.Combine(systemInfo.Tilde, path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));

                    return new Folder(folder.ID, path, syncState, new FolderIgnores(ignores.IgnorePatterns, ignores.RegexPatterns));
                });

            cancellationToken.ThrowIfCancellationRequested();

            var folders = await Task.WhenAll(folderConstructionTasks);
            this.folders = new ConcurrentDictionary<string, Folder>(folders.Select(x => new KeyValuePair<string, Folder>(x.FolderId, x)));

            this.OnFoldersChanged();
        }
        private async Task LoadStartupDataAsync(CancellationToken cancellationToken)
        {
            logger.Debug("Startup Complete! Loading startup data");

            // There's a race where Syncthing died, and so we kill the API clients and set it to null,
            // but we still end up here, because threading.
            cancellationToken.ThrowIfCancellationRequested();
            var apiClient = this.apiClient.GetAsserted();

            var systemTask = apiClient.FetchSystemInfoAsync();
            var versionTask = apiClient.FetchVersionAsync();
            
            cancellationToken.ThrowIfCancellationRequested();

            await Task.WhenAll(systemTask, versionTask);

            cancellationToken.ThrowIfCancellationRequested();

            this.systemInfo = systemTask.Result;
            await this.LoadConfigDataAsync(this.systemInfo.Tilde, false, cancellationToken);

            cancellationToken.ThrowIfCancellationRequested();

            this.Version = versionTask.Result;
            
            this.StartedTime = DateTime.UtcNow;
            this.IsDataLoaded = true;
            this.OnDataLoaded();
        }