我有一段代码可以搜索多个第三方API。我根据搜索条件将搜索分为两组。我开始两次搜索都是因为每次搜索都非常及时,但如果第一组搜索结果匹配,我不想等待第二个搜索组完成。基本上我所拥有的是:
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;
所以我想在调用SearchByTelNum之前启动SearchByName,以防它找不到匹配项,但是如果找到匹配项我不想在返回匹配项之前等待SearchByName完成。如果我不再需要其结果,有没有办法简单地结束或取消该委托?
答案 0 :(得分:1)
我能够使用System.ComponentModel.BackgroundWorker解决我的问题。我不一定以预期的方式使用它,但它能够做我需要的。所以基本上我的新代码是:
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;
为了确保没有错误,我必须确保SearchByName定期检查bw.CancellationPending是否等于true,并在这种情况下结束方法。 CancelAsync不会结束工作线程,它只是警告工作线程调用者线程已取消它。
我也可以简单地使用
while(bw.IsBusy) System.Threading.Thread.Sleep(500)
等待方法完成,但如果在SearchByName中发生了不好的事情,你可能会在无限循环中永远等待。通过这种方式,我可以设置一个时间量,然后才能认为方法超时,并且调用者线程会继续生命。在这种情况下,由于我每隔0.5秒检查一次bw.IsBusy,超时长度等于timeOutCount / 2秒。
好的,我想我已经彻底回答了我自己的问题。
答案 1 :(得分:0)
我通过定义一个可中止的参数对象
来处理这个问题public class AbortableParameter<T>
{
public T Parameter { get; private set }
public bool ShouldAbort { get; set; }
public AbortableParameter(T parameter)
{
Parameter = parameter;
ShouldAbort = false;
}
}
只需使用要传递给委托的任何参数创建此类的实例,并保留对它的引用;如果委托应该退出,则将其设置为true。然后,代表需要定期检查ShouldAbort
,并在true
成为ShouldAbort
时正常退出。
这是缺点,代表必须定期检查,否则无论是否中止都无关紧要。
当{{1}}属性的set方法设置为true时,也可以使该方法终止委托,但这不是一个优雅的退出,在大多数情况下应该避免 - 但它确实有好处不要求代表投票。