简体   繁体   中英

Trying to time a backgroundworker and cancel it if it takes to long

I am parsing a webpage in a C# application and I want to be able to time how long it takes and cancel it if it exceeds a certain time. I looked into both Timer classes and I'm still drawing a blank. any help would be greatly appreciated.

I hope this will help you out

using System;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static BackgroundWorker worker;
        private static Timer workTimer;

        private static void Main(string[] args)
        {
            Console.WriteLine("Begin work");
            worker = new BackgroundWorker();
            worker.DoWork += worker_DoWork;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;
            worker.WorkerSupportsCancellation = true;
            worker.WorkerReportsProgress = true;
            worker.RunWorkerAsync();

            // Initialize timer
            workTimer = new Timer(Tick, null,  
                                  new TimeSpan(0, 0, 0, 10),  // < Amount of time to wait before the first tick.
                                  new TimeSpan(0, 0, 0, 10)); // < Tick every 10 second interval
            Console.ReadLine();


        }

        private static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            workTimer.Dispose();
            if (e.Cancelled) return;

            // Job done before timer ticked
            Console.WriteLine("Job done");
        }

        private static void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 12; i++)
            {
                // Cancel the worker if cancellation is pending.
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
                Console.WriteLine(i);
                Thread.Sleep(1000);                
            }
        }

        private static void Tick(object state)
        {
            // Stop the worker and dispose of the timer.
            Console.WriteLine("Job took too long");
            worker.CancelAsync();
            worker.Dispose();

            workTimer.Dispose();
        }
    }
}

There are two problems here:

  • Generating a request to cancel after a certain amount of time
  • Cancelling the parsing operation

For the first you can use a Timer, as you suggested, (there are actually three 'Timer' classes) - the one which will give you most chance of success is System.Threading.Timer. The callback for this will occur on a pool thread, so should happen even if your parsing operation is still running. (Get this working using a Debug.Print or a debugger before worrying about the actuall cancellation.)

For the second part, you need to have some way to tell your parsing process to give up - this could be a CancellationToken, or a global variable or a WaitEvent - there are a number of options, but it's hard to suggest the best one without knowing more about your parsing process and how much access you have to its code.

Of course, if you have sufficient access to the parsing code to be adding checks for cancellation, you could just be doing a if(DateTime.UtcNow > _timeoutAt) test, in which case you don't need the independent timer... (In case it's not obvious, you'd set _timeoutAt = DateTime.UtcNow.AddSeconds(xxx) before starting the parsing operation)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM