簡體   English   中英

如何暫停線程池中線程的執行一段時間而不完全阻塞線程?

[英]How do I pause execution of a thread in a thread pool for a certain amount of time without blocking the thread entirely?

我所擁有的是類似於此的東西:

//method being called by thread pool thread
public string someFunction(){
    string someString = "string";

    //Stuff happens

    //Need to wait for 5 seconds without blocking thread

    return someString;
}

問題是我需要將該方法的結果返回給調用它的方法,但是,我不希望它立即返回,我不想阻止該線程。 有沒有一種方法可以讓線程在該行暫停一段指定的時間並將線程釋放回線程池,然后在一些超時后,其中一個線程池線程從中斷處完成並完成功能和回報?


所有......在花了一些時間回答你的問題之后,我現在意識到,在我想要的環境中,做我想要實現的目標並不是那么可能。

雖然有點解釋。 我正在嘗試用c sharp創建一個基本的長輪詢網絡服務器,用於我正在構建的基於Web的聊天應用程序。 我想讓線程進入一個等待的方法,直到發生兩件事之一,或者為客戶端顯示數據,或者發生輪詢超時。 但是,我不希望線程被阻塞,我有一些時間過去實現了一些東西,每個客戶端都有一個線程,線程被阻塞並相信我......這不是一個好主意。 示例中的5秒是任意的,實際時間可能介於1到5分鍾之間。 最后,我最終可能會遇到的結構是一種客戶端管理線程。 一個線程,通過一個列表詢問每個客戶端客戶端是否有工作要做。 如果客戶端已達到其超時或其隊列中有數據等待,則將相應的方法分派到線程池中,並且客戶端管理線程繼續到下一個客戶端。

像這樣......

while(true){
    foreach(Client client in ClientList){
        //check if the client has something it needs done
        if(client.needsWork){
               //invoke the appropriate method asynchronously
               delegate = client.appropriateInvokable;
               delegate.beginInvoke();
        }
    }
}

非常感謝大家的幫助和耐心!

在查看了你的問題后,我發現它比在新線程上獲得定時器回調有點棘手。 真正的問題是你的調用被構造為同步返回一個值,所以你無法避免阻塞調用線程。 避免阻塞的正確方法是更改​​調用以使用異步回調,而不是直接返回值。 如果您有權訪問TPL,一個很好的方法是返回一個Task對象,然后調用者可以立即等待或注冊回調。


也就是說,對於時序回調方面,我有一些實用程序代碼,我用它來簡化在這些一次性計時器方案中使用System.Threading.Timer。 我已將其剪切為指定的功能並將其放在下面:

public sealed class TimerService
{
    /// <summary>
    ///   This method registers a call back to be called after a specified period of time.
    /// </summary>
    /// <param name = "duration">The duration after which to call back</param>
    /// <param name = "callback">The method to call back</param>
    public void WhenElapsed(TimeSpan duration, Action callback)
    {
        if (callback == null) throw new ArgumentNullException("callback");

        //Set up state to allow cleanup after timer completes
        var timerState = new TimerState(callback);
        var timer = new Timer(OnTimerElapsed, timerState, Timeout.Infinite, Timeout.Infinite);
        timerState.Timer = timer;

        //Start the timer
        timer.Change((int)duration.TotalMilliseconds, Timeout.Infinite);
    }

    private void OnTimerElapsed(Object state)
    {
        var timerState = (TimerState)state;
        timerState.Timer.Dispose();
        timerState.Callback();
    }

    private sealed class TimerState
    {
        public TimerState(Action callback)
        {
            Callback = callback;
        }

        public Timer Timer { get; set; }

        public Action Callback { get; private set; }
    }
}

使用System.Threading.Timer類。 請參閱上面的MSDN鏈接。

接受的答案也是我所需要的,雖然看了一下之后我認為我們可以將它降低到這一點。 在我們都知道並喜歡的JScript函數之后命名它似乎是合適的...

public static void SetTimeout(Action callback, int milliseconds)
{
    Timer t = null;
    t = new Timer((state) => { t.Dispose(); callback(); }, null, dueTime: milliseconds, period: Timeout.Infinite);
}
public static Timer SetInterval(Action callback, int milliseconds)
{
    return new Timer((state) => { callback(); }, null, dueTime: milliseconds, period: milliseconds);
}
public static void ClearInterval(Timer t)
{
    t.Dispose();
}

要真的不阻止,保持相同的線程,等待5秒......

var until = Environment.TickCount + 5000;
while(Environment.TickCount < until);

有一個CPU持續5秒! 我真的希望你沒有一個核心可用於這個過程。

不過,這就是讓線程在沒有阻塞的情況下等待5秒的意思。 沒有等待某事的線程正在使用CPU時間。 雖然我們努力讓我們的CPU忙碌,只要他們有工作要做,我們就會努力讓他們忙於實際工作。

有時類似於上面的代碼用於納秒級的非常小的暫停,以避免在線程想要在進展之前看到的條件很快發生時的上下文切換。

這在這里沒有價值,因為線程的時間片通常在20ms到180ms的范圍內,它顯然會在5秒的時間內上升。

雖然我們經常想避免線程阻塞,並且可能會花費相當長的時間來避免它,但在這種情況下,如果我們真的必須保持在同一個線程上,那么我們就是浪費CPU並且無論如何都要進行上下文切換,所以我們越早阻止越好。 最簡單的方法是Thread.Sleep(5000)

或者,由於未能通過阻塞來交付三個要求中的一個(不阻塞,保持在同一個線程並同步返回到方法,導致5秒延遲),我們可以改為另外兩個。

如果我們使用回調,那么我們不會將值返回給調用線程,但是我們將阻止線程不必要地阻塞,這可能是最好的整體方法。 這將需要更多的重組。

當然,如果我們能夠找到一種方法來避免三個要求中的另一個,我們等待5秒鍾,那么所有其他問題就會消失,我們會快5秒!

這兩種方法都比涉及Thread.Sleep任何方法都好(98%的代碼調用可以在某處改進的東西,接近100%的代碼調用它的值大於2左右)。 如果沒有更多關於為什么你需要在第一時間等待5秒的情況下,如何做到這一點很難給出明確的建議。

暫無
暫無

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

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