C# 经常性后台任务

C# 经常性后台任务,c#,task-parallel-library,async-await,c#-5.0,C#,Task Parallel Library,Async Await,C# 5.0,我刚刚开始尝试使用任务而不是线程,并尝试实现一个具有后台清理任务的对象,该任务每5分钟运行一次,只要该对象正在使用,但不应阻止垃圾收集 一些粗制滥造的东西显然是行不通的 public class Foo : IDisposable { private CancellationTokenSource _tokenSource = new CancellationTokenSource(); public Foo() { Cleanup();

我刚刚开始尝试使用任务而不是线程,并尝试实现一个具有后台清理任务的对象,该任务每5分钟运行一次,只要该对象正在使用,但不应阻止垃圾收集

一些粗制滥造的东西显然是行不通的

public class Foo : IDisposable
{
    private CancellationTokenSource _tokenSource = new CancellationTokenSource();

    public Foo()
    {
        Cleanup();      
    }

    public void Dispose()
    {
        _tokenSource.Cancel();
    }

    public void Cleanup()
    {
        Task.Delay(TimeSpan.FromSeconds(5), _tokenSource.Token).ContinueWith(t => 
        {
            //Do Work
            if (!_tokenSource.IsCancellationRequested)
            {
                Cleanup();
            }
        }, TaskContinuationOptions.NotOnCanceled);
    }
}
正确的实施方法是什么

var f = new Foo();
var r = new WeakReference(f);
Thread.Sleep(TimeSpan.FromSeconds(15));
f.Dispose();
f = null;
System.GC.Collect();
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(r.IsAlive);
在回答I3arnon的问题时,我使用IDisposable,因为当我处理完对象时,我希望它被垃圾收集。例如,如果下面没有取消任务的f.Dispose,则f不会被垃圾回收,或者清理任务被取消。有没有更好的实施方法

var f = new Foo();
var r = new WeakReference(f);
Thread.Sleep(TimeSpan.FromSeconds(15));
f.Dispose();
f = null;
System.GC.Collect();
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine(r.IsAlive);

这够好吗?您还可以通过接受在while中运行的委托,使该类成为泛型类和可重用类。我真的不知道为什么你需要它成为一个IDisposable虽然

public class Foo : IDisposable
{
    private CancellationTokenSource _tokenSource = new CancellationTokenSource();

    public Foo()
    {
        Task.Run(async () => await CleanupAsync());
    }

    public void Dispose()
    {
        _tokenSource.Cancel();
    }

    public async Task CleanupAsync()
    {
        while (!_tokenSource.Token.IsCancellationRequested)
        {
           // Do whatever cleanup you need to.

           await Task.Delay(TimeSpan.FromSeconds(5),_tokenSource.Token);
        }
    }
}
可以删除Task.Run中的async和Wait。它们只是为了清晰起见。
Task.Run=>cleanupsync

这够好吗?您还可以通过接受在while中运行的委托,使该类成为泛型类和可重用类。我真的不知道为什么你需要它成为一个IDisposable虽然

public class Foo : IDisposable
{
    private CancellationTokenSource _tokenSource = new CancellationTokenSource();

    public Foo()
    {
        Task.Run(async () => await CleanupAsync());
    }

    public void Dispose()
    {
        _tokenSource.Cancel();
    }

    public async Task CleanupAsync()
    {
        while (!_tokenSource.Token.IsCancellationRequested)
        {
           // Do whatever cleanup you need to.

           await Task.Delay(TimeSpan.FromSeconds(5),_tokenSource.Token);
        }
    }
}
可以删除Task.Run中的async和Wait。它们只是为了清晰起见。
Task.Run=>cleanupsync

实现dispose允许您使用。这是一个很好的简洁易懂的简写,我已经完成了。我知道,但我怀疑他是否会在同一个使用范围内使用每5秒做一次事情的类。可以说,这取决于他为什么每5秒清理一次—这本身就是一种奇怪的做法。实现dispose允许您使用。这是一个很好的简洁易懂的简写,我已经完成了。我知道,但我怀疑他是否会在同一个使用范围内使用每5秒做一次事情的类。可以说,这取决于他为什么每5秒钟清理一次——这本身就是一种奇怪的做法。试试看,在.NET中没有确定性对象终结。试试看,在.NET中没有确定性对象终结。