c# – 在实现时间受限的方法时,我应该中止工作线程还是让它运行?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 在实现时间受限的方法时,我应该中止工作线程还是让它运行?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3246字,纯文字阅读大概需要5分钟。
内容图文
![c# – 在实现时间受限的方法时,我应该中止工作线程还是让它运行?](/upload/InfoBanner/zyjiaocheng/821/ea57ff5afeaa4e5a8a2ec03828816cef.jpg)
我目前正在为现有应用程序编写基于Web服务的前端.为此,我使用WCF LOB Adapter SDK,它允许创建自定义WCF绑定,将外部数据和操作公开为Web服务.
SDK提供了一些实现的接口,并且它们的一些方法是时间限制的:实现期望在指定的时间跨度内完成其工作或抛出TimeoutException.
调查让我想到了问题“Implement C# Generic Timeout”,明智地建议使用工人线程.有了这些知识,我可以写:
public MetadataRetrievalNode[] Browse(string nodeId, int childStartIndex,
int maxChildNodes, TimeSpan timeout)
{
Func<MetadataRetrievalNode[]> work = () => {
// Return computed metadata...
};
IAsyncResult result = work.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeout)) {
return work.EndInvoke(result);
} else {
throw new TimeoutException();
}
}
但是,如果工作线程超时,则不清楚如何处理工作线程.人们可以忘记它,就像上面的代码那样,或者可以中止它:
public MetadataRetrievalNode[] Browse(string nodeId, int childStartIndex,
int maxChildNodes, TimeSpan timeout)
{
Thread workerThread = null;
Func<MetadataRetrievalNode[]> work = () => {
workerThread = Thread.CurrentThread;
// Return computed metadata...
};
IAsyncResult result = work.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeout)) {
return work.EndInvoke(result);
} else {
workerThread.Abort();
throw new TimeoutException();
}
}
现在,中止一个线程被普遍认为是错误的.它打破了正在进行的工作,泄漏资源,使用锁定进行混乱,甚至不能保证线程实际上会停止运行.也就是说,HttpResponse.Redirect()每次调用都会中止一个线程,IIS似乎对此非常满意.也许它已经准备好以某种方式处理它.我的外部应用程序可能不是.
另一方面,如果我让工作线程继续运行,除了资源争用增加(池中可用线程较少)之外,无论如何都不会泄漏内存,因为work.EndInvoke()永远不会被调用?更具体地说,工作返回的MetadataRetrievalNode []数组不会永远存在吗?
这只是选择两个邪恶中较小的一个问题,还是有办法不中止工作线程并仍然回收BeginInvoke()使用的内存?
解决方法:
好吧,首先关闭Thread.Abort并不像它使用它那么糟糕.在2.0中对CLR进行了一些改进,修复了中止线程的几个主要问题.注意,这仍然很糟糕,所以避免它是最好的行动方案.如果你必须诉诸于中止线程,那么至少你应该考虑拆除中止源自的应用程序域.在大多数情况下,这将是非常具有侵入性的,并且无法解决可能的非托管资源损坏问题.
除此之外,在这种情况下中止还会产生其他影响.最重要的是你试图中止ThreadPool线程.我真的不确定最终结果是什么,它可能会有所不同,具体取决于框架的哪个版本正在发挥作用.
最好的做法是让你的Func< MetadataRetrievalNode []>委托在安全点轮询变量,以查看它是否应该自行终止执行.
public MetadataRetrievalNode[] Browse(string nodeId, int childStartIndex, int maxChildNodes, TimeSpan timeout)
{
bool terminate = false;
Func<MetadataRetrievalNode[]> work =
() =>
{
// Do some work.
Thread.MemoryBarrier(); // Ensure a fresh read of the terminate variable.
if (terminate) throw new InvalidOperationException();
// Do some work.
Thread.MemoryBarrier(); // Ensure a fresh read of the terminate variable.
if (terminate) throw new InvalidOperationException();
// Return computed metadata...
};
IAsyncResult result = work.BeginInvoke(null, null);
terminate = !result.AsyncWaitHandle.WaitOne(timeout);
return work.EndInvoke(result); // This blocks until the delegate completes.
}
棘手的部分是如何处理代理中的阻塞调用.显然,如果委托正在阻塞调用中,则无法检查终止标志.但是,假设阻塞调用是从一个罐装BCL等待机制(WaitHandle.WaitOne,Monitor.Wait等)启动的,那么你可以使用Thread.Interrupt来“戳”它,并且应该立即取消阻塞它.
内容总结
以上是互联网集市为您收集整理的c# – 在实现时间受限的方法时,我应该中止工作线程还是让它运行?全部内容,希望文章能够帮你解决c# – 在实现时间受限的方法时,我应该中止工作线程还是让它运行?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。