gpt4 book ai didi

c# - 在对象完成时取消任务

转载 作者:行者123 更新时间:2023-11-30 16:03:23 25 4
gpt4 key购买 nike

我有一个启动任务的类,并希望确保在对象被垃圾回收时任务停止。

我已经实现了 IDisposable 模式,以确保如果对象被手动处置或在 using block 中使用,则 Task 会正确停止。 但是,我不能保证最终用户会调用 Dispose() 或在 using block 中使用该对象。我知道垃圾收集器最终会调用终结器——这是否意味着任务仍在运行?

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 中提出添加一个从 Finalizer 设置并从任务观察到的 volatile bool。这是推荐的方法,还是有更好的方法来实现我的需要?

(我使用的是 .NET 4,因此使用 TaskFactory.StartNew 而不是 Task.Run)

编辑:

为了给这个问题提供一些上下文——上面的代码片段中实际上没有显示:我正在创建一个网络客户端类,它有一种通过定期向服务器发送数据包来保持事件的机制。我选择不将所有这些细节都放在示例中,因为它与我的具体问题无关。然而,我真正想要的是用户能够将 KeepAlive bool 属性设置为 true,这将启动一个任务,每 60 秒向服务器发送一次数据。如果用户将该属性设置为 false,则任务停止。 IDisposable 让我完成了 90% 的工作,但是它依赖于用户正确地处理它(明确地或通过使用)。我不想向用户公开保持事件任务以便他们明确取消,我只想要一个“简单的”KeepAlive = true/false 来启动/停止任务并且我希望任务在用户完成时停止对象 - 即使他们没有妥善处理它。我开始认为这是不可能的!

最佳答案

我会草拟一个答案。我不是 100% 相信这会奏效。 Finalization 是一个复杂的问题,我并不精通。

  1. 不能有从任务到任何应该完成的对象的对象引用。
  2. 您不能从终结器中接触未知安全的其他对象。内置的 .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 的引用。

关于c# - 在对象完成时取消任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36447462/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com