我有一个启动任务的类,并希望确保该任务在对象被垃圾收集时停止。
我已经实现了 IDisposable 模式,以确保如果手动处理对象或在 using 块中使用对象,则任务会正确停止。However,我不能保证最终用户会调用 Dispose() 或在 using 块中使用该对象。我知道垃圾收集器最终会调用终结器 - 这是否意味着任务继续运行?
public class MyClass : IDisposable
{
private readonly CancellationTokenSource feedCancellationTokenSource =
new CancellationTokenSource();
private readonly Task feedTask;
public MyClass()
{
feedTask = Task.Factory.StartNew(() =>
{
while (!feedCancellationTokenSource.IsCancellationRequested)
{
// do finite work
}
});
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
feedCancellationTokenSource.Cancel();
feedTask.Wait();
feedCancellationTokenSource.Dispose();
feedTask.Dispose();
}
}
~MyClass()
{
Dispose(false);
}
}
建议在这个问题 https://stackoverflow.com/questions/19196889/cancelling-tasks-in-the-dispose-method添加一个易失性布尔值,该布尔值是从终结器设置并从任务中观察到的。这是推荐的,还是有更好的方法来实现我的需要?
(我使用的是 .NET 4,因此使用 TaskFactory.StartNew 而不是 Task.Run)
EDIT:
为了给这个问题提供一些背景信息——上面的代码片段中实际上没有显示:我正在创建一个网络客户端类,它有一个通过定期向服务器发送数据包来保持活动状态的机制。我选择不在示例中添加所有这些细节,因为它与我的具体问题无关。然而,我真正想要的是用户能够将 KeepAlive 布尔属性设置为 true,这将启动一个任务,每 60 秒向服务器发送数据。如果用户将该属性设置为 false,则任务将停止。 IDisposable 让我完成了 90% 的工作,但是它依赖于用户正确地处理它(显式地或通过使用)。我不想向用户公开保持活动任务,以便他们显式取消,我只想要一个“简单”KeepAlive = true/false 来启动/停止任务,并且我希望任务在用户完成时停止该物体 - 即使他们没有正确处置它。我开始觉得这是不可能的!
我将画出一个答案。我不是 100% 相信这会起作用。最终确定是一个复杂的问题,我对此并不精通。
- 任务中不能有对象引用到任何应该最终确定的对象。
- 您不能从终结器中触摸不安全的其他对象。内置的 .NET 类通常不会记录此安全属性。你不能依赖它(通常)。
class CancellationFlag { public volatile bool IsSet; }
您现在可以在任务和任务之间共享此类的实例MyClass
。该任务必须轮询标志并MyClass
必须设置它。
为了确保任务永远不会意外引用外部对象,我将像这样构造代码:
Task.Factory.StartNew(TaskProc, state); //no lambda
static void TaskProc(object state) { //static
}
这样你就可以显式地将任何状态线程化state
。这至少是一个例子CancellationFlag
但在任何情况下都不会提及MyClass
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)