I have a piece of code that searches several third party APIs. I have the searches split into 2 groups based on the search criteria. I start both searches because each search is quite timely, but if the first group of searches results in an match I don't want to wait around for the second search group to finish. So basically what I have is:
Dictionary<string, string> result = null;
NameSearchDelegate nameDel = new NameSearchDelegate(SearchByName);
IAsyncResult nameTag = nameDel.BeginInvoke(name, null, null);
if(!string.IsNullOrWhiteSpace(telNum))
{
result = SearchByTelNum(telNum);//Will return null if a match is not found
}
if(null == result)
{
result = nameDel.EndInvoke(nameTag);
}
//End the delegate to prevent memory leak
//else
//{
// nameDel.EndInvoke(nameTag)
//}
return result;
So I want to start the SearchByName before I call SearchByTelNum in case it does not find a match, however if it does find a match I don't want to have to wait for SearchByName to finish before returning the match. Is there any way to simply end or cancel that delegate if I no longer need its result?
I was able to solve my problem using System.ComponentModel.BackgroundWorker. I wasn't necessarily using it in the way it is intended to be used but it was able to do what I needed. So basically what my new code looks like is:
Dictionary<string, string> telResult = null,
nameResult = null;
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += (obj, e) => nameResult = SearchByName(name, bw);
bw.RunWorkerAsync();
if(!string.IsNullOrWhiteSpace(telNum))
telResult = SearchByTelNum(telNum);//Will return null if a match is not found
if(telResult != null)
{
bw.CancelAsync;
return telResult;
}
bool hasTimedOut = false;
int i = timeOutCount;
while (bw.IsBusy && !hasTimedOut)
{
System.Threading.Thread.Sleep(500);
if (0 == --i) hasTimedOut = true;
}
return nameResult;
And to make sure there are no bugs, I had to make sure that SearchByName periodically checks if bw.CancellationPending equals true, and ends the method in that case. CancelAsync does not end the worker thread, it simply alerts the worker thread that caller thread has canceled it.
Also I could have simply used
while(bw.IsBusy) System.Threading.Thread.Sleep(500)
to wait for the method to complete, but if something bad happens in SearchByName you could end up waiting forever in an infinite loop. This way I can set an amount of time before the method is considered to have timed out and the caller thread just goes on with life. In this case, since I check bw.IsBusy every .5 seconds, the timeout length is equal to timeOutCount / 2 seconds.
Ok I think I have thoroughly answered my own question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With