private static async Task DoFetch(Random rng, IUserInfo userInfo, DownloadForm downloadWindow, CancellationToken cancellationToken)
        {
            List <IVideoInfo> videos = new List <IVideoInfo>();

            while (true)
            {
                downloadWindow.AddStatusMessage("Fetching " + userInfo.ToString() + "...");

                try {
                    FetchReturnValue fetchReturnValue;
                    int Offset = 0;
                    do
                    {
                        try {
                            await Task.Delay(rng.Next(55000, 95000), cancellationToken);
                        } catch (Exception) { }
                        if (cancellationToken.IsCancellationRequested)
                        {
                            break;
                        }
                        fetchReturnValue = await userInfo.Fetch(Offset, true);

                        Offset += fetchReturnValue.VideoCountThisFetch;
                        if (fetchReturnValue.Success)
                        {
                            videos.AddRange(fetchReturnValue.Videos);
                        }
                    } while (fetchReturnValue.Success && fetchReturnValue.HasMore);
                    break;
                } catch (Exception ex) {
                    downloadWindow.AddStatusMessage("Error during " + userInfo.ToString() + ": " + ex.ToString());
                    break;
                }
            }

            if (!cancellationToken.IsCancellationRequested)
            {
                try {
                    await Task.Delay(rng.Next(55000, 95000), cancellationToken);
                } catch (Exception) { }
            }
            downloadWindow.AddStatusMessage("Fetched " + videos.Count + " items from " + userInfo.ToString() + ".");
            DownloadFetched(videos, downloadWindow);
        }
        private async Task Run()
        {
            while (true)
            {
                try {
                    await Task.Delay(3000, CancelToken);
                } catch (Exception) { }

                if (CancelToken.IsCancellationRequested)
                {
                    return;
                }

                try {
                    IUserInfo earliestUserInfo = null;
                    lock (ContainerLock) {
                        foreach (IUserInfo u in UserInfos)
                        {
                            if (u.AutoDownload && (earliestUserInfo == null || u.LastRefreshedOn < earliestUserInfo.LastRefreshedOn))
                            {
                                earliestUserInfo = u;
                            }
                        }
                    }

                    if (earliestUserInfo != null)
                    {
                        DateTime earliestStartTime = earliestUserInfo.LastRefreshedOn.AddHours(7.0);
                        DateTime now = DateTime.UtcNow;
                        if (earliestStartTime <= now)
                        {
                            try {
                                await DoFetch(RNG, earliestUserInfo, Form, CancelToken);
                            } finally {
                                if (!CancelToken.IsCancellationRequested)
                                {
                                    earliestUserInfo.LastRefreshedOn = now;
                                    if (earliestUserInfo.Persistable)
                                    {
                                        UserInfoPersister.AddOrUpdate(earliestUserInfo);
                                        UserInfoPersister.Save();
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception ex) {
                    Form.AddStatusMessage("Error during fetch: " + ex.ToString());
                }
            }
        }