【问题标题】:Cancel Thread Sleep取消线程休眠
【发布时间】:2020-05-23 08:09:39
【问题描述】:

我有一个带有 2 个运行线程的简单控制台应用程序。

第一个线程正在测量一些值,第二个线程查找用户输入并执行一些鼠标移动。

while (true)
{
    if (Input.IsKeyDown(VC_L))
    {
        Mouse.Move(300, 500);
        Thread.Sleep(thread1_delay);
        Mouse.Move(670, 300);
        Thread.Sleep(thread1_delay);
        Mouse.Move(870, 700);
        Thread.Sleep(thread1_delay);
    }
}

问题是我想在获得另一个键作为输入后立即停止第二个线程。但它不起作用,因为线程仍在睡眠并且没有反应。

【问题讨论】:

  • 一种选择是使用Task.DelayCancellationToken
  • 如果你需要取消睡眠,你不应该使用 Thread.Sleep,你应该使用任务和取消令牌。要回答您的问题,您可以使用Thread.Interrupt 将其从当前/下一次睡眠中唤醒,但这就像用“服用止痛药”回答“我怎样才能在不伤害食物的情况下射掉食物”的问题
  • 我认为你可以使用 Thread 的 Abort 方法
  • @RamilAliyev 有 Eric Lippert 而不是 stackoverflow.com/a/1560567/1612975
  • Thread.Interrupt 和 Thread.Abort 都是错误的答案。正确的答案是您不应该尝试取消 Thread.Sleep,而应该使用其他可以取消的东西。如果您不想/不能使用任务,请使用 WaitHandle,如 ManualResetEvent,并在给定的超时时间内等待它。当超时发生时,等待结束,或者如果您发出句柄信号,则等待结束。

标签: c# multithreading sleep


【解决方案1】:

第二个线程在唤醒时应检查布尔值。当您的条件满足时,您应该将此值设置为 false。现在,当第二个线程唤醒时,它将完成它的执行。

【讨论】:

    【解决方案2】:

    只需使用CancellationToken 即可完成

    传播应该取消操作的通知。

    示例

    public static async Task DoFunkyStuff(CancellationToken token)
    {
       // a logical escape for the loop
       while (!token.IsCancellationRequested)
       {
          try
          {
             Console.WriteLine("Waiting");
             await Task.Delay(1000, token);
          }
          catch (OperationCanceledException e)
          {
             Console.WriteLine("Task Cancelled");
          }
       }
       Console.WriteLine("Finished");
    }
    

    用法

    static async Task Main(string[] args)
    {
    
       var ts = new CancellationTokenSource();
    
       Console.WriteLine("Press key to cancel tasks");
       var task = DoFunkyStuff(ts.Token);
    
       // user input
       Console.ReadKey();
    
       Console.WriteLine("Cancelling token");
    
       // this is how to cancel
       ts.Cancel();
    
       // just to prove the task has been cancelled
       await task;
    
       // because i can
       Console.WriteLine("Elvis has left the building");
       Console.ReadKey();
    }
    

    结果

    Press key to cancel tasks
    Waiting
    Waiting
    Waiting
    Waiting
    Waiting
    Cancelling token
    Task Cancelled
    Finished
    Elvis has left the building
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      相关资源
      最近更新 更多