14

我有一个线程从网络或串行端口获取一些数据。如果 5 秒内没有收到数据,线程必须终止(或返回 false)。

换句话说,如果线程运行时间超过 5 秒,它必须停止。

我用 C# 编写,但任何 .NET 语言都可以。

4

6 回答 6

9

有两种方法:

1.封装超时

从网络或串口读取数据的线程可以测量从它开始时经过的时间,并等待数据不超过剩余时间。网络通信 API 通常提供指定操作超时的方法。因此,通过做简单的DateTime算术,您可以在工作线程中封装超时管理。

2.外部超时

使用另一个线程(或者如果可行的话在主线程中执行)等待工作线程在一定的时间限制内完成,如果没有,则中止它。像这样:

// start the worker thread
...

// give it no more than 5 seconds to execute
if (!workerThread.Join(new TimeSpan(0, 0, 5)))
{    
    workerThread.Abort();
}

建议:我会坚持第一个解决方案,因为它会带来更清洁和可维护的设计。但是,在某些情况下,可能有必要为此类工作线程的“硬”中止提供方法。

于 2010-12-21T17:10:38.643 回答
4

任何一种机制都应该允许您在读取时指定超时。例如,您可以NetworkStream.ReadTimeout在执行读取之前设置为 5000。您应该能够为串行端口做类似的事情。

已超时的读取将返回 0 Stream.Read()- 这是您可以判断是否实际发生超时的方法。

请注意,Thread.Abort()对于可能导致的一些严重问题,从 .NET 2.0 开始不推荐使用 using。理论上你可以使用Thread.Interrupt(),但是当线程在非托管代码(包括 I/O)中被阻塞时,这不会做任何事情。使用读取超时是解决此问题的正确方法。

于 2010-12-21T17:07:38.073 回答
3

如果您使用托管代码来阻塞线程,您可以使用它Thread.Abort来中止执行。如果您使用的是第 3 方代码或 COM 互操作,则无法终止线程执行。唯一的方法是将设置Thread.isBackroundThread为true,然后终止进程......

于 2010-12-21T17:03:28.890 回答
2

您提到您正在从“网络”阅读。如果您NetworkStream用于阅读,则可以指定ReadTimeout5000 (以毫秒为单位)。如果没有读取数据,它将等待 5 秒然后返回。但是,如果它正在处理或阅读中,我认为它也可能会返回,所以要小心。我从来没有对串行 API 做过任何事情,所以我不确定那里是否有这样的设置。

于 2010-12-21T17:10:03.963 回答
2

这是一个双线程解决方案。

例子:

Thread tParent = new Thread(new ThreadStart(() =>
{
    Thread t = new Thread(AsyncMethod);
    t.Start();
    Thread.Sleep(5000);
    if (t.IsAlive) t.Abort();
}));

记住:

使用这样的方法是一种不好的做法。不推荐调用Thread.Abort()方法。改用Thread Synchronizationusing WaitHandles。例如,AutoResetEvent

于 2010-12-21T17:12:24.270 回答
1

我想你需要一个观察者线程。同时启动另一个线程,并将串口线程作为该线程的参数传递。以五秒钟的睡眠启动观察者并检查线程的状态。

现在至于终止线程,请参阅alex的答案,它刚刚好!

于 2010-12-21T17:04:22.027 回答