C# - 多线程暂停

问题描述 投票:0回答:2

这是我用C#编写的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace xyz
{
    class Program
    {
        Thread t1, t2;
        static void Main(string[] args)
        {
            Program go = new Program();
            go.actual();
        }
        public void actual()
        {
            t1 = new Thread(timer);
            t2 = new Thread(inputting);
            t1.Start();
            t2.Start();
        }
        public void timer()
        {
            Thread.Sleep(5000);
            t2.Abort();
            Console.WriteLine("5 seconds passed!");
        }
        public void inputting()
        {
            Console.WriteLine("Please wait 5 seconds...");
            Console.ReadKey();
        }
    }
}

现在,问题是,当控制台说“5秒钟过去了!” (在中止t2线程后),它不会立即退出。此文本在此处停留几秒钟,然后控制台退出。

问题是,如果我在线程中止之前按下一个键(ReadKey方法),它会显示“5秒钟过去了!”文本,然后它立即退出。

如果我没有点击任何键,并且没有发生ReadKey方法,它只会显示文本几秒钟。

这是为什么?这是一个错误吗?我可以解决它吗?

c# multithreading system
2个回答
0
投票

您看到的结果对我来说似乎是合理的,调用Thread.Abort不会以某种方式取消阻止控制台,因此它仍将等待输入。无论如何,你应该避免调用Thread.Abort,因为不能保证它会按预期工作。在线程中构建取消支持是一种更好的方法,有很多方法可以做到这一点。

或者,只需使用已经内置的Task Parallel Library


0
投票

从你的评论我看到你基本上想要在一段时间后超时Console.ReadKey电话。不幸的是,ReadKey没有超时参数。好的,可以。我们可以将它包装在一个方法中。您不需要使用任何异步机制来完成此任务。只需在同步轮询循环中使用Console.KeyAvailable即可。

public static class ConsoleEx
{
  public static bool TryReadKey(TimeSpan timeout, out ConsoleKeyInfo keyinfo)
  {
    var cts = new CancellationTokenSource();
    return TryReadKey(timeout, cts.Token, out keyinfo);
  }

  public static bool TryReadKey(TimeSpan timeout, CancellationToken cancellation, out ConsoleKeyInfo keyinfo)
  {
    keyinfo = new ConsoleKeyInfo();
    DateTime latest = DateTime.UtcNow.Add(timeout);
    do
    {
        cancellation.ThrowIfCancellationRequested();
        if (Console.KeyAvailable)
        {
            keyinfo = Console.ReadKey();
            return true;
        }
        Thread.Sleep(1);
    }
    while (DateTime.UtcNow < latest);
    return false;
  }
}

然后你会像这样使用它。

public static void Main()
{
  ConsoleKeyInfo cki;
  if (ConsoleEx.TryReadKey(TimeSpan.FromSeconds(5), out cki))
  {
    Console.WriteLine("ReadKey returned a value.");
  }
  else
  {
    Console.WriteLine("ReadKey timed out.
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.