如何在事件触发后重置 Task.Delay()?

Tre*_*ter 1 c# filesystemwatcher delay reset

在我的 FileSystemWatcher 超过 5 分钟没有收到任何更改后,我试图让一些代码触发。

我目前的方法是await Task.Delay();在更改后调用 a ,希望用户到时完成。这显然不是要走的路。

所以我的问题是:如何在事件触发后重置 Task.Delay()?

tza*_*chs 5

你不能“重置” a Task.Delay,但你可以重置一个计时器,这使它成为解决这个问题的理想选择。

下面是一个例子:

    private System.Threading.Timer timer;

    public void Start()
    {
        timer = new System.Threading.Timer(_ => fireMyCode());
        restartTimer();
    }

    private void onFileChanged(object sender, EventArgs e)
    {
        restartTimer();
    }

    private void restartTimer()
    {
        timer.Change(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
    }
Run Code Online (Sandbox Code Playgroud)

但是您不必使用计时器,您仍然可以使用Task.Delay附加任务:这个想法是等待两个任务,延迟和等待文件更改(您可以使用TaskCompletionSource从事件“创建”任务)。如果延迟任务首先完成,请触发您的代码。

下面是一个例子:

    TaskCompletionSource<object> fileChanged = new TaskCompletionSource<object>();

    private void onFileChanged(object sender, EventArgs e)
    {
        fileChanged.TrySetResult(null);
    }

    private async Task endlessLoop()
    {
        while (true)
        {
            await handleFilesNotChanged();
        }
    }

    private async Task handleFilesNotChanged()
    {
        Task timeout = Task.Delay(TimeSpan.FromMinutes(5));
        Task waitForFile = fileChanged.Task;

        if (await Task.WhenAny(timeout, waitForFile) == timeout)
        {
            fireMyCode();
        }
        fileChanged = new TaskCompletionSource<object>();
    }
Run Code Online (Sandbox Code Playgroud)