private void BWDoWork(object sender, DoWorkEventArgs ex)
        {
            SiteProfile profile = (SiteProfile)ex.Argument;

            string arguments = profile.GetArguments();
            FakeIP fakeip    = FakeIP.From(arguments); // fake ip
            FakeUA fakeua    = FakeUA.From(arguments); // fake ua

            // report begin state
            bgWork.ReportProgress(-1, null);

            for (int i = 1; i <= profile.PlayTimes; i++)
            {
                /** Report progress, states.
                 * progress is indicated in e.UserState (value: progressFullness)
                 */
                double progressFullness = (double)i / profile.PlayTimes;

                try
                {
                    string response = PlaySite(arguments, fakeip, fakeua, profile.IsReadResponse);
                    bgWork.ReportProgress(100, new object[] { progressFullness, i, response });
                }
                catch (Exception err)
                {
                    bgWork.ReportProgress(100, new object[] { progressFullness, i, err.Message });
                    return;
                }

                /** No Sleep. Check CancellationPending and continue
                 */
                if (profile.DelayMin <= 0)
                {
                    if (bgWork.CancellationPending)
                    {
                        return;
                    }
                    else
                    {
                        continue;
                    }
                }

                /** Sleep. Check CancellationPending every 100ms
                 */
                int sleep_count_100ms = profile.DelayMax > profile.DelayMin ?
                                        random.Next(profile.DelayMin, profile.DelayMax) * 10
                    : profile.DelayMin * 10;

                while (sleep_count_100ms-- > 0)
                {
                    System.Threading.Thread.Sleep(100);

                    if (bgWork.CancellationPending)
                    {
                        return;
                    }
                }
            }
        }
        public void StartBgWork(SiteProfile profile)
        {
            // Init background work
            bgWork = new BackgroundWorker
            {
                WorkerSupportsCancellation = true,
                WorkerReportsProgress      = true
            };
            bgWork.DoWork             += BWDoWork;
            bgWork.ProgressChanged    += BWProgressChanged;
            bgWork.RunWorkerCompleted += BWCompleted;

            bgWork.RunWorkerAsync(profile);
        }