c#-对象完成后取消任务
作者:互联网
我有一个启动任务的类,并希望确保在垃圾回收对象时任务停止.
我已经实现了IDisposable模式,以确保如果手动放置对象或在using块内使用该对象,则Task可以正确停止.但是,我不能保证最终用户将调用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);
}
}
在this question中建议添加挥发性的bool,该挥发性的bool是在Finalizer中设置的,并从任务中观察到.是建议这样做,还是有更好的方法来实现我的需求?
(我使用的是.NET 4,因此使用TaskFactory.StartNew而不是Task.Run)
编辑:
为了给问题提供一些背景信息-上面的代码片段中并未实际显示:我正在创建一个网络客户端类,该类具有通过定期向服务器发送数据包来保持活动的机制.我选择不将所有这些详细信息放在示例中,因为它与我的特定问题无关.但是,我真正想要的是用户能够将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
}
这样,您可以通过状态显式地线程化任何状态.这至少是CancellationFlag的一个实例,但在任何情况下都不会引用MyClass.
标签:finalizer,task-parallel-library,idisposable,task,c 来源: https://codeday.me/bug/20191118/2031219.html