杀死C#中的任务

时间:2020-08-17 07:21:33

标签: c# wpf

在处理生成温度曲线的异步任务时,我遇到了一些问题。

Dim X as Long
X = 2
MsgBox Cells(X, X).Address 'it will return the address of Row 2, Columns 2 ($B$2)
'Or
MsgBox Range("A" & X).Address 'returns "$A$2"

然后我用回车按钮点击功能的另一种形式调用它。

        public static async Task genLotProfile(string lotno,string filename, string datch)
        {
            int count = 0;

            while (true)
            {
                count += 1;

                //Move this following code to new method 
                var csv = new StringBuilder();

                if (!File.Exists(filename))
                {
                    File.Create(filename); 
                }


                Tprofile temp = getLogData(datch);

                if (count == 1)
                {
                    var header = string.Format("Lotno,Temperature,Date,DataChannel");
                    csv.AppendLine(header);
                }


                var newLine = string.Format("{0},{1},{2},{3}", lotno,temp.temperature, temp.date, temp.dataChannel);

                csv.AppendLine(newLine);

                if (!File.Exists(filename))
                {
                    File.WriteAllText(filename, csv.ToString());
                }

                File.AppendAllText(filename, csv.ToString());

                //task delay
                await Task.Delay(30000);
            }
        }

在我的案例中,杀死一个任务有哪些惯例?

3 个答案:

答案 0 :(得分:4)

请勿对await Task.Delay(30000)使用无限循环。

请改为使用间隔为30秒的计时器。然后在必要时停止计时器。

如果涉及WPF UI元素,请使用DispatcherTimer。如果您使用的是.NET Core,还请使用File方法的异步版本:

private readonly DispatcherTimer timer = new DispatcherTimer
{
    Interval = TimeSpan.FromSeconds(30)
};

public MainWindow()
{
    InitializeComponent();

    timer.Tick += OnTimerTick;
    timer.Start();
}

private async void OnTimerTick(object sender, EventArgs e)
{
    ...

    if (!File.Exists(filename))
    {
        await File.WriteAllTextAsync(filename, csv.ToString());
    }
    else
    {
        await File.AppendAllTextAsync(filename, csv.ToString());
    }

    ...
}

随时通过

停止计时器
timer.Stop();

答案 1 :(得分:4)

Clemens所说的话似乎几乎与您的用例完全匹配,因为您实际上希望每30秒执行一次,然后在用户请求时停止。

但是,从另一个角度回答您的问题,“杀死任务”的典型方法是CancellationTokenSource + CancellationToken。令牌是充当标记的东西,它表示“立即死亡”(开始虚假,可以一次设置为真实状态,不可清除),源是标志的控制器,允许您升起标志。

请记住,尽管这是“取消任务的标准方法”,但这不是强制停止的方法。该任务必须定期检查该令牌,并查看其是否已取消。

现在您可能想知道为什么要拥有这样的令牌,为什么不仅仅使用volatile / atomic / bool / etc。答案是:CancellationToken是一次性的,它可以作为值传递,与其他对象合并/链接,在设置时订阅以获取回调,它具有CancellationToken.ThrowIfCancellation方法,该方法引发可以快速摆脱任何嵌套的if / switch / while / for的异常-框架可以理解此异常,并且希望可以处理该异常,并且不会使进程崩溃,以及(...)

最重要的是,它被人们认可。如果有人看到CancellationToken,就知道它是要中断/停止/中断某些处理。

每当您考虑使用bool阻止某事时,请改用CancellationToken。

编辑:我要写一个例子,但是迈克尔·兰德尔击败了我:)

答案 2 :(得分:3)

唯一的惯例是我们不使用Abort中止线程。

肯定的办法是使用合作社CancellationToken。如果您需要长时间运行的任务来进行IO work和/或UI更新,那么这将是理想的选择。否则,您也可以像值得Clemensanswer中那样使用Timer

public static async Task GenLotProfile(string lotno, string filename, string datchm, CancellationToken token)
{
   try
   {

      int count = 0;

      while (!token.IsCancellationRequested)
      {
         //...
         await Task.Delay(30000, token);
      }

   }
   catch (OperationCanceledException e)
   {
      // if you want to suppress the task cancelled exception that may be thrown
   }
   _logger.Debug("GenLotProfile Cancelled");
}
相关问题