protected override async Task StartPrivateAsync()
                {
                    ReleaseSemaphoreSlim();
                    try
                    {
                        switch (Status)
                        {
                        case NetworkStatus.NotStarted:
                        {
                            Status = NetworkStatus.Networking;
                            if (UploadedCloudFolder == null)
                            {
                                var fc = new Modifiers.FolderCreator(cloudFolder, this.windowsFolder.Name);
                                var messageAppendedEventHandler = new MessageAppendedEventHandler((msg) => { OnMessageAppended($"[FC]{msg}"); });
                                OnMessageAppended("Creating folder...");
                                fc.MessageAppended += messageAppendedEventHandler;
                                await fc.StartUntilCompletedAsync();

                                fc.MessageAppended -= messageAppendedEventHandler;
                                //switch (fc.Status)
                                //{
                                //    case NetworkStatus.Completed:
                                //        {
                                OnMessageAppended("Folder created");
                                UploadedCloudFolder = fc.CreatedCloudFolder;
                                OnProgressChanged(0, 0);
                            }
                            //NetworkingCount--;
                            var windowsFiles = await this.windowsFolder.GetFilesAsync();

                            lock (subTasks)
                            {
                                foreach (var f in windowsFiles)
                                {
                                    subTasks.Add(new FileUploader(UploadedCloudFolder, f, f.Name));
                                }
                            }
                            var windowsFolders = await this.windowsFolder.GetFoldersAsync();

                            lock (subTasks)
                            {
                                foreach (var f in windowsFolders)
                                {
                                    var folderUploader = new FolderUploader(UploadedCloudFolder, f);
                                    subTasks.Add(folderUploader);
                                }
                            }
                            long currentProgress = 1, totalProgress = windowsFiles.Count + 1;
                            OnProgressChanged(currentProgress, totalProgress);
                            CurrentProgressChanged?.Invoke(1);
                            TotalProgressChanged?.Invoke(windowsFiles.Count + 1);
                            Func <Networker, Task> action;
                            if (Status == NetworkStatus.Paused)
                            {
                                action = new Func <Networker, Task>(async(st) =>
                                    {
                                        await st.WaitUntilCompletedAsync();
                                    });
                            }
                            else
                            {
                                action = new Func <Networker, Task>(async(st) =>
                                    {
                                        await st.StartUntilCompletedAsync();
                                    });
                            }
                            IEnumerable <Task> tasks;
                            lock (subTasks)
                            {
                                var currentProgressChangedEventHandler = new TotalProgressChangedEventHandler((dif) =>
                                    {
                                        MyLogger.Assert(dif == 1);
                                        CurrentProgressChanged?.Invoke(dif);
                                        OnProgressChanged(currentProgress += dif, totalProgress);
                                    });
                                var totalProgressChangedEventHandler = new TotalProgressChangedEventHandler((dif) =>
                                    {
                                        TotalProgressChanged?.Invoke(dif);
                                        OnProgressChanged(currentProgress, totalProgress += dif);
                                    });
                                tasks = subTasks.ToList().Select(async(st) =>
                                    {
                                        if (st.GetType() == typeof(CloudFile.Uploaders.FolderUploader))
                                        {
                                            var fu = st as CloudFile.Uploaders.FolderUploader;
                                            fu.CurrentProgressChanged += currentProgressChangedEventHandler;
                                            fu.TotalProgressChanged   += totalProgressChangedEventHandler;
                                            await action(st);
                                            fu.CurrentProgressChanged -= currentProgressChangedEventHandler;
                                            fu.TotalProgressChanged   -= totalProgressChangedEventHandler;
                                        }
                                        else
                                        {
                                            await action(st);
                                            CurrentProgressChanged?.Invoke(1);
                                            OnProgressChanged(++currentProgress, totalProgress);
                                        }
                                    });
                            }
                            await Task.WhenAll(tasks);

                            //NetworkingCount++;
                            Status = NetworkStatus.Completed;
                            return;
                            //        }
                            //    case NetworkStatus.ErrorNeedRestart:
                            //        {
                            //            this.Status = NetworkStatus.ErrorNeedRestart;
                            //            return;
                            //        }
                            //    default: throw new Exception($"Status: {Status}");
                            //}
                        }

                        case NetworkStatus.Paused:
                        {
                            Status = NetworkStatus.Networking;
                            await Task.WhenAll(subTasks.ToList().Select(async(st) => { await st.StartAsync(); }));

                            //Status = NetworkStatus.Completed;
                        } break;

                        default:
                        {
                            OnMessageAppended($"Status: {Status}, no way to start");
                        } break;
                        }
                    }
                    catch (Exception error)
                    {
                        throw error;
                    }
                    finally
                    {
                        await WaitSemaphoreSlimAsync();
                    }
                }
                private async Task <NetworkStatus> VerifyFolder()
                {
                    Status = NetworkStatus.Networking;
                    long currentProgress = 0, totalProgress = 1;

                    OnProgressChanged(currentProgress, totalProgress);
                    if (cloudFolder.Name != windowsFolder.Name)
                    {
                        OnMessageAppended($"Name not consistent, Cloud: {cloudFolder.Name}, Local: {windowsFolder.Name}");
                        return(NetworkStatus.ErrorNeedRestart);
                    }
                    var folderVerifiers = new List <Tuple <CloudFile, Windows.Storage.StorageFolder> >();

                    {
                        if (!await GetCloudSubFolders())
                        {
                            return(NetworkStatus.ErrorNeedRestart);
                        }
                        Dictionary <string, Windows.Storage.StorageFolder> localSubFolders = new Dictionary <string, Windows.Storage.StorageFolder>();
                        foreach (var f in await windowsFolder.GetFoldersAsync())
                        {
                            if (!cloudSubFolders.ContainsKey(f.Name))
                            {
                                OnMessageAppended($"Cloud Folder doesn't exist: {f.Name}");
                                return(NetworkStatus.ErrorNeedRestart);
                            }
                            localSubFolders.Add(f.Name, f);
                        }
                        foreach (var p in cloudSubFolders)
                        {
                            if (!localSubFolders.ContainsKey(p.Key))
                            {
                                OnMessageAppended($"Local Folder doesn't exist: {p.Key}");
                                return(NetworkStatus.ErrorNeedRestart);
                            }
                            folderVerifiers.Add(new Tuple <CloudFile, Windows.Storage.StorageFolder>(p.Value, localSubFolders[p.Key]));
                            localSubFolders.Remove(p.Key);
                        }
                        MyLogger.Assert(localSubFolders.Count == 0);
                    }
                    {
                        if (!await GetCloudSubFiles())
                        {
                            return(NetworkStatus.ErrorNeedRestart);
                        }
                        Dictionary <string, Windows.Storage.StorageFile> localSubFiles = new Dictionary <string, Windows.Storage.StorageFile>();
                        foreach (var f in await windowsFolder.GetFilesAsync())
                        {
                            if (!cloudSubFiles.ContainsKey(f.Name))
                            {
                                OnMessageAppended($"Cloud File doesn't exist: {f.Name}");
                                return(NetworkStatus.ErrorNeedRestart);
                            }
                            localSubFiles.Add(f.Name, f);
                        }
                        foreach (var p in cloudSubFiles)
                        {
                            if (!localSubFiles.ContainsKey(p.Key))
                            {
                                OnMessageAppended($"Local File doesn't exist: {p.Key}");
                                return(NetworkStatus.ErrorNeedRestart);
                            }
                        }
                        OnProgressChanged(++currentProgress, totalProgress += cloudSubFiles.Count);
                        CurrentProgressChanged?.Invoke(1);
                        TotalProgressChanged?.Invoke(cloudSubFiles.Count);
                        OnMessageAppended("Verifying subfiles...");
                        int filesVerified = 0;
                        foreach (var p in cloudSubFiles)
                        {
                            var localFile = localSubFiles[p.Key];
                            var stream    = await localFile.OpenStreamForReadAsync();

                            var localMd5 = await Libraries.GetSha256ForWindowsStorageFile(stream);

                            stream.Dispose();
                            if (localMd5 != p.Value || p.Value == null)
                            {
                                OnMessageAppended($"{p.Key} content not consistent, Cloud: {p.Value}, Local: {localMd5}");
                                CurrentProgressChanged?.Invoke(-filesVerified - 1);
                                TotalProgressChanged?.Invoke(-cloudSubFiles.Count);
                                return(NetworkStatus.ErrorNeedRestart);
                            }
                            OnProgressChanged(++currentProgress, totalProgress);
                            CurrentProgressChanged?.Invoke(1);
                            ++filesVerified;
                            localSubFiles.Remove(p.Key);
                        }
                        OnMessageAppended("Subfiles verified.");
                        MyLogger.Assert(localSubFiles.Count == 0);
                    }
                    OnProgressChanged(currentProgress, totalProgress += folderVerifiers.Count);
                    TotalProgressChanged?.Invoke(folderVerifiers.Count);
                    ReleaseSemaphoreSlim();
                    OnMessageAppended("Waiting for subfolders to be verified...");
                    try
                    {
                        await Task.WhenAll(folderVerifiers.Select(async(tuple) =>
                        {
                            var totalProgressChangedEventHandler = new TotalProgressChangedEventHandler((difference) =>
                            {
                                OnProgressChanged(currentProgress, totalProgress += difference);
                                TotalProgressChanged?.Invoke(difference);
                            });
                            var currentProgressChangedEventHandler = new TotalProgressChangedEventHandler((difference) =>
                            {
                                //MyLogger.Assert(difference == 1);
                                OnProgressChanged(currentProgress += difference, totalProgress);
                                CurrentProgressChanged?.Invoke(difference);
                            });
                            var verifier = new Verifiers.FolderVerifier(tuple.Item1, tuple.Item2);
                            verifier.TotalProgressChanged   += totalProgressChangedEventHandler;
                            verifier.CurrentProgressChanged += currentProgressChangedEventHandler;
                            await verifier.StartUntilCompletedAsync();
                            verifier.TotalProgressChanged   -= totalProgressChangedEventHandler;
                            verifier.CurrentProgressChanged -= currentProgressChangedEventHandler;
                        }));

                        return(NetworkStatus.Completed);
                    }
                    finally
                    {
                        await WaitSemaphoreSlimAsync();
                    }
                }