簡體   English   中英

C#-XX秒后停止線程

[英]C# - Stop a thread after XX seconds

我在C#中使用線程,我希望它在40秒后停止。 實際上,我啟動了它,運行了40秒,然后它停止了。 是否可以使用超時或計時器?

有兩種方法:

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();
}

當然,可以啟動一個計時器,然后在計時器到期時殺死線程,但是您自己做起來比使用Richter的Power Threading庫之類的實用程序更好,它可以使您在異步任務上設置超時。

您打算如何停止線程? 中止線程不是一個好主意(如果您打算這樣做),例如,有關更多信息,請參閱中止計時器線程 使用諸如Power Threading庫之類的工具可以使您更優雅地使線程超時,如果您選擇自己這樣做,則需要考慮如何優雅地結束線程。

根據阻塞操作的級別,對及時性的容忍度(即必須停止接近40秒)以及線程必須優雅退出的方式,有幾種選擇。

內部合作

如果該線程不需要外部控制或信號,並且具有通常短暫的阻塞操作(某些時間短於40秒),則可以使用秒表來測量經過的時間,然后正常退出。 另外,您可以用DateTime標記開始時間,然后通過從DateTime.Now減去開始時間來進行定期檢查。

合作,外部

這是另一個線程在確定是第二個線程退出的時間之后,將信號發送到另一個線程。 這意味着另一個線程必須通過實際檢查條件來配合,這意味着任何阻塞操作(例如I / O)都不能長時間阻塞,因此它可以進行檢查。 這里有一些選擇:

  • 取消 T1創建CancellationTokenSources ,並將s.Token作為狀態數據到線程T2。 T2定期檢查s.Token. IsCancellationRequested
  • 使用Tasks 取消 這非常相似,但是使用.NET 4.0 Task Parallel Library而不是使用顯式任務
  • 條件檢查 T1設置布爾值或T2可以檢查的其他值。 當條件滿足時, T2退出

非合作

T2無法檢查某些條件(即無法合作)時,這是一個可能的選擇,可能是因為它執行了一些您無法控制的長時間阻塞操作,例如,調用不提供異步操作的第三方API或可取消的選項。 在這種情況下, T1可以通過執行Thread.Join( timeout )並隨后調用Thread.Abort()來優雅地嘗試停止T2 。注意:避免這種情況,並且在框架中已棄用了此方法。

最后,

如果在T2中調用了Thread.Sleep ,則可以將以下兩種技術之一與上述技術結合使用:

  • 中斷 T1可能在檢查T2ThreadStateThreadState.WaitSleepJoin之后,在T2上調用Thread.Interrupt
  • 旋轉睡眠 而不是使用Thread.Sleep實現“旋轉睡眠”。 基本上,這類似於常規睡眠,但是您會以較小的間隔睡眠N次,然后返回一個布爾值,指示較小的睡眠是否被中斷(當然,它必須捕獲此異常)。 然后在為true時退出(例如,您執行SpinSleep(20, 50) Thread.Sleep(10000)而不是Thread.Sleep(10000) SpinSleep(20, 50)

您可以通過在線程上使用Join(超時40秒)來達到類似目的。 之后,您可以嘗試正常關閉線程(您必須自己提供方法)或使用Abort-但這並不建議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM