In order to perform long-running (let it be search in this context) operation, I put the loading logic inside a TPL task, so the general method Search() is called on background thread. Search() operation can be long enough, so I need the ability to cancel it properly, using the CancellationToken. But the Search() operation did not return until it finished, so I have to do some logic in order to implement convenient and (!) fast cancellation.
Using WaitHandle's I can implement something like this:
private void StartSearch() // UI thread
{
CancellationTokenSource s = new CancellationTokenSource();
Task.Factory.StartNew(() => StartSearchInternal(s.Token), s.Token)
}
private void StartSearchInternal(CancellationToken token) // Main Background Thread
{
ManualResetEvent eHandle = new ManualResetEvent(false);
Task.Factory.StartNew(() => Search(eHandle ), TaskScheduler.Default);
WaitHandle.WaitAny(new [] { eHandle, token.WaitHandle });
token.ThrowIfCancellationRequested();
}
private IEnumerable<object> Search(ManualResetEvent e) // Another Background thread
{
try
{
// Real search call, i.e. to database, service, or AD, doesn't matter
return RealSearch();
}
catch {} // Here, for simplicity of question, catch and eat all exceptions
finally
{
try
{
e.Set();
}
catch {}
}
}
It's seems to me that this is not so elegant solution, that can be made.
Q: Is there any other approaches for this task?