【问题标题】:C# Utilizing cancellation tokens for each Task createdC#为创建的每个任务使用取消令牌
【发布时间】:2020-08-18 04:13:22
【问题描述】:

我有一个任务方法,它在我的 MainWindow 中生成温度曲线,但当用户将大量(生产的物品)的数据输入烤箱并每 30 秒记录一次温度时,它以另一种形式调用。

public static async Task genLotProfile(string lotno,string filename, string datch,CancellationToken token)

try
{
       //get temperature and do other stuff
       Tprofile temp = getLogData(datch); 
       
       //task delay
       while (!token.IsCancellationRequested)
      {
          //Task delay
          await Task.Delay(30000, token);
      }
}
catch (OperationCanceledException e)
{

}

我的想法是每次输入很多内容时都在输入表单中的输入按钮功能上调用它。

private void EnterBtn_Click(object sender, RoutedEventArgs e)
{
   //do other stuff

   //Call generate temp profile
    string filename = MainWindow.getTempProfileName(MainWindow.datachannel, lotnoTBX.Text);
                
    CancellationToken token = source.Token;
                
    MainWindow.genLotProfile(lotnoTBX.Text, filename, MainWindow.datachannel, token);
}

我还有一个单独的取消课程

    class Cancel
    {
        CancellationTokenSource _source;

        public Cancel(CancellationTokenSource source)
        {
            _source = source;
        }

        public void cancelTask()
        {
            _source.Cancel();
        }
    }

问题是我将有多个任务在我的条件下运行,并且当用户从烤箱中取出批次时,我想在另一个输出表单上使用 Cancel 类终止特定任务,如果出现这种情况,取消令牌会终止我正在运行的所有任务我执行以下操作

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Cancel c = new Cancel(source); 
c.cancelTask();

【问题讨论】:

  • CancellationToken 没有真正的魔力,基本上所有监听或轮询取消的任务都会取消。要获得更细粒度的控制,您需要使用多个。请注意,您可以将它们链接到单个令牌源并具有回调以具有更复杂的结构。虽然很难给出任何进一步的建议,但不知道你到底想做什么
  • 所以如果我说我做 CancellationToken token1 = source.Token; , CancellationToken token2 = source.Token;这会使它成为单独的令牌,我可以杀死特定的任务吗?
  • 虽然CancellationToken 是结构体,但结构体实际上包含对源的引用,因此复制结构体仍然为您提供相同的取消机制。您需要创建单独的CancellationTokenSources 才能访问单独的令牌
  • 如果 CTS 本身已经是包装器,为什么还需要 CTS 包装器类? Cancel 类完全没用。最后,CancellationTokenSource 实现了IDisposable。这是一些usage example。
  • 在不知道你之前的问题的情况下,为什么你有 while 循环似乎也很奇怪。它在这里没有任何意义。除此之外,请考虑使用非静态 GetTempProfileName 方法和 CancellationTokenSource 成员创建一个类。然后,您将在 Task 和 CancellationTokenSource 之间建立一对一的关联。或者更好的是,使用带有计时器成员的类。

标签: c# wpf task


【解决方案1】:

您需要为每个任务创建新的 CancellationTokenSource:

private async void EnterBtn_Click(object sender, RoutedEventArgs e)
{
   //do other stuff

   //Call generate temp profile
    string filename = MainWindow.getTempProfileName(MainWindow.datachannel, lotnoTBX.Text);

    CancellationTokenSource source = new CancellationTokenSource();                
    CancellationToken token = source.Token;
                
    await MainWindow.genLotProfile(lotnoTBX.Text, filename, MainWindow.datachannel, token);
}

取消特定任务时,只需调用正确的令牌实例的cancel()即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多