EDIT : I just realized that KeithS was approaching a good answer. The basic idea is that you call the XPathDocument constructor , which takes a Stream , which wraps a FileStream . The object you pass must implement the Read(byte[], int, int) function Read(byte[], int, int) to call the wrapped FileStream Read function, or throw an exception if the operation has been disabled. Here is a sample code:
class XmlStream : FileStream { DateTime deadline; public XmlStream(string filename, TimeSpan timeout) : base(filename, FileMode.Open) { deadline = DateTime.UtcNow + timeout; } public override int Read(byte[] array, int offset, int count) { if (DateTime.UtcNow > deadline) throw new TimeoutException(); return base.Read(array, offset, count); } }
Here is the code that reads in document but expires in 1 second:
bool found = true; using(var stream = new XmlStream(document, TimeSpan.FromSeconds(1))) try { xpath = new XPathDocument(stream); } catch (TimeoutException) { found = false; }
If you create a separate thread instead of executing BeginInvoke , you can simply interrupt the thread when the timer BeginInvoke (or someone clicks Cancel). Although thread interruption is usually impractical because it can hold a lock or have global data in an inconsistent state, in this case it should be good because your thread will not hold a lock or global data.
Here is the code for this method, which does the same as the previous sample:
bool found = false; thread = new Thread(() => { xpath = new XPathDocument(document); found = true; }); thread.Start(); thread.Join(TimeSpan.FromSeconds(1)); thread.Abort();
If you are not comfortable interrupting threads in your own application domain, you can create a document in another application domain and call AppDomain.Unload if it takes too much time. This will require some sorting, but there probably won't be too much overhead.
The ultimate way to kill a process is to run it in a separate process and use some kind of remote access interface to access it. Probably even more erratic than other parameters, however, since you have to worry about finding the executable, passing parameters, some users completing it, etc.