user3362814
user3362814

Reputation: 41

timeout if method takes too long to finish

I am trying to timeout and throw an exception after waiting a specified amount of time, and am wondering if the way I'm currently doing it is best.

    class Timeout
    {

        XmlDocument doc;
        System.Object input;

        public Timeout(XmlDocument doc, System.Object input)
        {
            this.doc = doc;
            this.input = input;
        }

        public void run()
        {
            if (input is Stream)
            {
                doc.Load((Stream)input);
            }
            else if (input is XmlReader)
            {
                doc.Load((XmlReader)input);
            }
            else if (input is TextReader)
            {
                doc.Load((TextReader)input);
            }
            else
            {
                doc.Load((string)input);
            }
            System.Threading.Thread.CurrentThread.Abort();
        }

    }

    private void LoadXmlDoc(XmlDocument doc, System.Object input)
    {

        Timeout timeout = new Timeout(doc, input);
        System.Threading.Thread timeoutThread = new System.Threading.Thread(new ThreadStart(timeout.run));
        timeoutThread.Start();
        System.Threading.Thread.Sleep(this.timeout * 1000);
        if (timeoutThread.IsAlive)
        {
            throw new DataSourceException("timeout reached", timeout.GetHashCode());
        }
    }

This current approach does work, so I'm just wondering if there's a simpler/better way to go about accomplishing the same thing.

Upvotes: 3

Views: 2379

Answers (3)

user3362814
user3362814

Reputation: 41

What I ended up doing:

    class Timeout
    {
        XmlDocument doc;
        System.Object input;

        public Timeout(XmlDocument doc, System.Object input)
        {
            this.doc = doc;
            this.input = input;
        }

        public void run()
        {
            if (input is Stream)
            {
                doc.Load((Stream)input);
            }
            else if (input is XmlReader)
            {
                doc.Load((XmlReader)input);
            }
            else if (input is TextReader)
            {
                doc.Load((TextReader)input);
            }
            else
            {
                doc.Load((string)input);
            }
        }
    }

    private void LoadXmlDoc(XmlDocument doc, System.Object input)
    {
        Timeout timeout = new Timeout(doc, input);
        System.Threading.Thread timeoutThread = new System.Threading.Thread(new ThreadStart(timeout.run));
        timeoutThread.Name = "XmlWorker" + threadNumber++;
        timeoutThread.Start(); 
        if (!timeoutThread.Join(this.timeout)) //Join returning false implies the timeout was reached
        {
            if (timeoutThread.IsAlive)
                timeoutThread.Abort();
            throw new DataConnectionException("timeout reached: " + this.timeout.Milliseconds + "ms", new TimeoutException(this.timeout.Milliseconds));
        }
    }

Upvotes: 1

Will D
Will D

Reputation: 884

Try doing something like this:

try
{
    var cts = new System.Threading.CancellationTokenSource();

    cts.CancelAfter(TimeSpan.FromSeconds(0.01));

    var tw = Task.Run<System.Xml.XmlDocument>(() =>
    {
        var doc = new System.Xml.XmlDocument();
        doc.Load("https://maps.googleapis.com/maps/api/geocode/xml?address=1+Exchange+Plaza+,+Floor+26+,+NY&sensor=false");
        return doc;
    }, cts.Token);

    var xml = await tw;
}
catch (TaskCanceledException e)
{

}

Upvotes: 3

bubbinator
bubbinator

Reputation: 495

In addition to my comment (here's the link from it), here is some more information regarding threading. Basically it comes down to learning the different designs/libraries, what their pros and cons are, which one suits your needs best.

From my understanding, and hopefully someone with more knowledge on the subject will pitch in on this, there are basically 2 different categories that you can put the threading designs in, synchronous and asynchronous. You have used the asynchronous design, employing the thread pool. If you want to stick with this design, you can try using the Task or, for synchronous operations Parallel.

On a side note: I'm not sure as to the wisdom behind using an exception to handle simple logic. In other words, the exception could be simply replace with returning a boolean.

Upvotes: 1

Related Questions