代码之家  ›  专栏  ›  技术社区  ›  CrazyCoder

使用任务。用c#代码运行,在特定时间内运行代码

  •  0
  • CrazyCoder  · 技术社区  · 4 年前

    我有一段用c#编写的代码,用于处理数据。

    string status;
    log.Info("Starting the Process");
    StartProcessing(); // takes 10-12 mins usually 
    
    var task = Task.Run(() =>
    {
        do
        {
            status = GetStatus();
            log.Info("Status inside loop : " + status);
        } while (status != "Complete")
    });
    
    if (task.Wait(TimeSpan.FromMinutes(Convert.ToDouble(15))))
    {
        log.Info("Processing finished");
    }
    else
    {
        log.Info("Process did not complete in 15 mins");
        log.Info("Stopping the Process");
        StopProcessing(); // this takes 2-3 mins usually.
        log.Info("Process stopped");
    }
    

    StartProcessing()方法实际上启动了对数据的一些后台处理。它不返回任何值,也不等待方法完成。因此,我们添加了一个do-while循环来检查处理的状态。如果状态已完成,则退出循环并继续。

    现在,要求已经改变,为处理设置了超时。如果处理时间超过5分钟,那么我们必须停止该过程。因此,我将代码打包在Task中。如上所示运行,并写一个if-else条件来检查时间。

    这似乎没有按预期工作,因为当我运行代码时,这是我得到的日志信息。

    Starting the Process  
    Status inside loop : Processing
    Status inside loop : Processing
    Status inside loop : Processing
    Status inside loop : Processing --> this line is repeated multiple times with in 15 mins.  
    Process did not complete in 15 mins.  
    Stopping the Process  
    Status inside loop : Processing  
    Status inside loop : Processing  
    Status inside loop : Processing --> why is it going back to do while after coming out ?
    Process stopped 
    

    即使在出狱后,处决仍将继续。我在这里做错了什么吗?
    任何建议都非常有帮助。

    0 回复  |  直到 4 年前
        1
  •  2
  •   PMF    4 年前

    您需要添加在给定时间后终止后台任务的代码。为此,你最好介绍一个 CancellationToken 您的处理任务。请执行以下操作:

    CancellationTokenSource source = new CancellationTokenSource(TimeSpan.FromMinutes(5));
    StartProcessing(source.Token);
    

    然后,在您的处理任务中,定期致电 token.IsCancellationRequested 如果这是真的,则中止。

        2
  •  0
  •   weichch    4 年前

    如果您有权访问的源代码 StartProcess 然后就像@PMF说的那样,路过 CancellationToken 这种方法是有效的方法。

    否则,您可以使用创建自己的可取消任务 TaskCompletionSource CancellationTokenSource :

    Task<bool> ProcessAsync(TimeSpan timeout)
    {
        var tcs = new TaskCompletionSource<bool>();
        var cts = new CancellationTokenSource();
    
        // If task canceled, set to return false
        cts.Token.Register(() => tcs.TrySetResult(false));
    
        // Cancel after timeout
        cts.CancelAfter(timeout);
    
        // Start process.
        StartProcess();
    
        // Start waiting until complete or canceled.
        Task.Run(() =>
        {
            while (GetStatus() != "Complete" && !cts.IsCancellationRequested)
            {
            }
    
            if (cts.IsCancellationRequested)
            {
                // Task has been canceled due to timeout.
                tcs.TrySetResult(false);
            }
            else
            {
                // Task done. Status is "Completed".
                tcs.TrySetResult(true);
            }
        });
    
        return tcs.Task;
    }
    

    然后等待 ProcessAsync :

    // Or ProcessAsync(TimeSpan.FromMinutes(5)).Result for sync method
    var isCompleted = await ProcessAsync(TimeSpan.FromMinutes(5));
    if (!isCompleted)
    {
        StopProcess();
    }