0

我需要一个允许我在线程运行超过 X 秒时执行某些操作的逻辑。

就像在这个非常丑陋的例子中一样,它会每秒检查一次,如果workerThread运行了 10 分钟或更长时间,它会显示一条消息......

var timeWorking = TimeSpan.FromMinutes(0);
workerThread = new Thread(RunTask);
workerThread.Start(task);
while (workerThread.IsAlive)
{
    Thread.Sleep(TimeSpan.FromSeconds(1));
    timeWorking = timeWorking.Add(TimeSpan.FromSeconds(1));
    if (timeWorking.TotalMinutes < 10) continue;
    timeWorking = TimeSpan.FromMinutes(0);
    Console.Writeline("Here we go... the event")
}

请帮我把它做对......我应该使用什么Diagnostics.StopWatchSystem.Timers.Timer或者Threading.Timer

UPD:所有的答案让我更加困惑......

任务是检查是否workerThread运行超过 X 时间,如果是,则调用某个方法,重置计时器并再次检查workerThread自上次调用该方法以来现在是否运行超过 X 时间……等等等等……

UPD2:基本上我有一个线程根据从 AmazonSQS 队列中提取的信息进行处理。SQS 队列消息具有可见性超时。如果任务花费的时间超过默认可见性超时 - 消息将在任务完成之前返回队列。然后它将被另一台机器拾取。为避免这种情况,我需要延长 SQS 消息的可见性超时。所以我可以通过定期检查线程是否仍然如此来做到这一点,isALive然后我可以在消息可见性超时中增加几分钟。大约一分 50 秒后,我应该再次检查线程是否仍然存在,isALive然后再添加几分钟,依此类推。

4

5 回答 5

2

根据您的描述,我认为System.Timers.Timer更适合。但是,这取决于。如果你想用计时器对 UI 做一些事情。Forms.Timer 更好。

在任何一种情况下,您都可以简单地检查当计时器经过(或 Ticked)时线程是否仍然处于活动状态,如果是,则执行一些操作。

例如

    timeThreadStarted = DateTime.Now;
    workerThread = new Thread(RunTask);
    System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
    workerThread.Start(task);
//...

static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    if(workerThread != null && workerThread.IsAlive)
    {
        Console.WriteLine("thread has been running for {0}!", DateTime.Now - timeThreadStarted);
    }
}

这会在 1 秒后检查线程状态。如果它仍然活着,那么它已经运行了至少一秒钟。

这样做的好处是不会阻塞任何线程。如果你有一个 UI 并且你想这样做,那么你不能阻止 UI 线程(它会变得无响应并提供糟糕的用户体验)。

于 2012-08-28T15:53:27.800 回答
2

既然你知道线程需要在十分钟后做某事,为什么不简单地在计时器上使用一个间隔,如下所示:

var interval = 1000 * 60 * 10; // ten minutes
var timer = new System.Timers.Timer(interval) { AutoReset = false };
timer.Elapsed += ((sender, eventArgs) =>
    {
        // Do your work here...
    });

workerThread = new Thread(RunTask);
workerThread.Start(task);
timer.Start();

这样您就不会检查每一秒,您将在所需的时间后执行您的代码。

于 2012-08-28T15:55:33.397 回答
1

您也可以Thread.Join使用http://msdn.microsoft.com/en-us/library/23f7b1ct.aspxTimeSpan上的示例,这样您就不必执行.Thread.Sleep

注意:任何一种方法都会阻塞调用线程,直到时间过去。不适用于主/UI 线程。

于 2012-08-28T15:59:55.083 回答
0

您可以使用一个 Timer,一旦触发了经过的时间,它将引发一个事件。

 private static void Main(string[] args)
    {
        var thread = new Thread(
            () =>
                {
                    var timer = new System.Timers.Timer
                        {
                            Interval = 10000, //10s
                            AutoReset = false, //only raise the elapsed event once
                        };
                    timer.Elapsed += timer_Elapsed;
                    timer.Start();
                    while (true)
                    {
                        Console.WriteLine("Running...");
                        Thread.Sleep(1000); //Always put a thread to sleep when its blocking so it does not waste CPU cycles.
                    }
                });
        thread.Start();
    }

    private static void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        //thread is running for more that X (10s) amount of seconds
        Console.WriteLine("Timer elapsed");
    }

这是一个简单的例子。在这个例子中,线程永远不会退出。但是您可以在必要时添加自己的逻辑来获得您想要完成的任务。

简短回答:是的,使用 System.Timers.Timer

于 2012-08-28T15:55:18.237 回答
-1

您可以使用任务等待方法,例如

var t = Task.Factory.StartNew(() => MyAction()); // MyAction is an action to be executed in parallel


bool check = t.Wait(10000); //wait for 10000 milliseconds
if (check)
{
 // all ok
}
else 
{
  // over time 
}

Wait 方法会阻塞,直到任务结束或发生超时。如果您不想阻塞主线程,您可以使用另一个并行工作的任务运行示例代码并检查工作任务。

于 2012-08-28T15:57:44.667 回答