6

当您启动线程时,有没有办法为线程应该(最大)存活多长时间设置一个值?

换句话说,使用“伪代码”,是否有这样的东西:

Thread t = new Thread();
t.start();
t.abort_after_x_seconds(30);

如果线程存活超过 30 秒,这将使线程中止。

编辑:我仍然无法让它工作,我最初拥有的是:

while(true)
{
    if(...)
    {
        Thread t = new Thread(new ThreadStart(startMethod));
        t.start();
    }
    Thread.sleep(...);
}

问题是有时线程会挂起(我没有实现线程的作用,所以我不知道确切原因(这是一个学校项目,我们在组织方面是菜鸟)),所以我想杀死那些线程。我尝试使用以下示例中的 Tasks 和 CancellationTokens,但是当 Task 挂起时,它无法检查是否发生了取消请求。

4

3 回答 3

7
  1. 大多数时候,您不应该使用Threads,Task而是使用 s。它们更方便、更高效。
  2. 中止某些事情是不安全的,您应该改用合作取消。如果您正在调用支持取消的方法,则只需向其传递一个取消令牌,该令牌将在 30 秒后取消。

所以你的代码可能看起来像这样(使用.Net 4.5):

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)));
var task = Task.Run(() => YourMethod(cts.Token), cts.Token);
于 2013-11-11T14:24:25.413 回答
1

[编辑:我的反应太慢了。但我将把它留在这里作为示例代码。]

为此,您应该使用合作取消。线程本身需要检测何时应该退出,并做出适当的响应。

有一种叫做 a 的东西,你CancellationToken可以CancellationTokenSource用它来实现这个目的。

甚至还有一个CancellationTokenSource构造函数可以让你设置超时。

下面是一些示例代码来演示它的使用:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        private void run()
        {
            using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = Task.Run(() => exampleOne(tokenSource.Token));
                task.Wait();
            }

            using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = Task.Run(() => exampleTwo(tokenSource.Token));
                task.Wait();
            }

            Console.WriteLine("Done.");
        }

        static void exampleZero()
        {
            Console.WriteLine("Starting exampleZero()");

            try
            {
                Thread.Sleep(10000); // Simulate work.
            }

            catch (OperationCanceledException)
            {
                Console.WriteLine("Operation cancelled.");
            }

            Console.WriteLine("Exiting exampleZero()");
        }

        static void exampleOne(CancellationToken cancellation)
        {
            Console.WriteLine("Starting exampleOne()");

            // Busy loop processing.

            while (!cancellation.IsCancellationRequested)
            {
                // Do some work.
            }

            Console.WriteLine("Exiting exampleOne()");
        }

        static void exampleTwo(CancellationToken cancellation)
        {
            Console.WriteLine("Starting exampleTwo()");

            while (!cancellation.WaitHandle.WaitOne(100)) // Wait 100ms between work.
            {
                // Do some work.
            }

            Console.WriteLine("Exiting exampleTwo()");
        }

        static void Main()
        {
            new Program().run();
        }
    }
}
于 2013-11-11T14:35:35.077 回答
0

正如评论者所说,使用Abort是不好的做法,不能保证立即中止。你为什么要保持线程活着?当分配给它的任务完成时,线程将被释放回池中。下次在线程上运行任务时,将通过创建另一个新线程或重新使用线程池中可用的线程池自动提供线程池。

听起来您的逻辑/代码很糟糕,需要修复而不是等待 x 秒然后终止它,这本身会导致问题。

也许您需要一个可以在 30 秒后计时的计时器,然后您可以禁用计时器并终止手头的任务。

于 2013-11-11T14:22:21.407 回答