使用从另一种方法调用的取消令牌定期运行任务

时间:2017-09-19 15:17:26

标签: c# wpf xaml asynchronous async-await

我试图每隔x分钟运行一次屏幕截图任务,但似乎当我想使用给定的取消令牌取消该任务时,它似乎没有做任何事情。

这是我的开始方法代码:

var CancellationTokenSource = new CancellationTokenSource();

        CancellationTokenSource?.Cancel();

        CancellationTokenSource = new CancellationTokenSource();

        var token = CancellationTokenSource.Token;
        await RunPeriodically(async () =>
        {

            var screenCaptured = TakeScreenshot();

            if (screenCaptured == null || CancellationTokenSource.Token.IsCancellationRequested)
                return;

            var correctUserName = Settings.Default.Username.Split('.');
            var parsedUsername = correctUserName[0] + " " + correctUserName[1];
            await ScreenshotHelper.UploadScreenshotAsync(ProjectName, "screenshotscontainer",
                screenCaptured.ToArray(), Environment.MachineName, parsedUsername);
            Console.WriteLine("Took Screenshot: " + DateTime.Now.ToString(CultureInfo.InvariantCulture));

        }, TimeSpan.FromSeconds(3), token);

这是定期运行代码:

public async Task RunPeriodically(Action action, TimeSpan interval, CancellationToken token)
    {
        while (true)
        {
            action();
            await Task.Delay(interval, token);
        }
    }

1 个答案:

答案 0 :(得分:0)

我想我已经敲了一个类的快速示例,它将运行一个进程,等待一段时间并再次启动进程而不会阻塞任何线程。

class RepeatableProcess
{
    private Timer  processTimer;
    private int delay;
    private CancellationTokenSource source;
    private CancellationToken token;
    private Action processToRun;
    private bool canStart = true;


    public RepeatableProcess(int delaySeconds,Action process)
    {
        delay = delaySeconds;
        processToRun = process;
    }

    public void Start()
    {
        if (canStart)
        {
            canStart = false;
            source = new CancellationTokenSource();
            token = source.Token;
            processTimer = new Timer(TimedProcess, token, Timeout.Infinite, Timeout.Infinite);
            processTimer.Change(0, Timeout.Infinite);
        }

    }

    public void Stop()
    {
        source.Cancel();
    }

    public void TimedProcess(object state)
    {

        CancellationToken ct = (CancellationToken)state;
        if (ct.IsCancellationRequested)
        {
            Console.WriteLine("Timer Stopped");
            processTimer.Dispose();
            canStart = true;
        }
        else
        {
            processToRun.Invoke();
            processTimer.Change(delay, Timeout.Infinite);
        }
    }

}

Start方法创建一个永不启动且永不重复的计时器。 然后立即启动该过程,仅运行一次。

TimedProcess方法检查取消并运行指定的进程。完成此过程后,计时器将设置为在指定的延迟后启动并仅运行一次。

当计时器触发时,它从线程池中获取一个线程。不存在溢出问题,因为在进程完成之前,计时器未设置为再次运行。

这个课程需要更多保护,但这只是一个例子。 希望这会有所帮助。