在中间退出Thread.Sleep的最佳方法

时间:2015-11-22 15:14:18

标签: c# multithreading

我有一些操作,有时我想停在中间:

bool contine;
foreach (var item in this)
{
    if (contine)
    {
        // do my stuss
    }
}   

此问题在foreach内有时我需要特定的延迟时间,所以我使用的是Thread.Sleep。 所以当我停止我的操作以防我仍然在这个Thread.Sleep内时,我的应用程序正在等待Thread.Sleep结束并且只停止我的操作,所以我可以退出中间的Thread.Sleep吗?

更新

我需要特定睡眠的原因是因为我正在播放数据包,并且每个数据包之间都有一个Time stamp所以这就是我需要睡眠的原因。

3 个答案:

答案 0 :(得分:6)

您可以使用也可以取消的Task.Delay。

private void Method(CancellationToken token)
{
    foreach (var item in this)
    {
        if (!token.IsCancellationRequested)
        {
            // do my stuss

            Task.Delay(1000, token).Wait(); // use await for async method
        }
        else break; // end
    }
}

当你想打电话时

var source = new CancellationTokenSource();
Method(source.Token);

当你想要取消时。

source.Cancel();

答案 1 :(得分:0)

一种可能的解决方案可能是使用您自己的Sleep方法(需要进行改进!):

/// <summary>
/// Contains extensions for threads.
/// </summary>
public static class ThreadExtensions
{
    /// <summary>
    /// Allows sleeping with cancellation.
    /// </summary>
    /// <param name="thread">The reference to the thread itself.</param>
    /// <param name="sleep">The amount of time to sleep in milliseconds.</param>
    /// <param name="source">An instance of <see cref="CancellationTokenSource"/> which can be used to signal the cancellation.</param>
    public static void InterruptableSleep(this Thread thread, int sleep, CancellationTokenSource source)
    {
        while (!source.IsCancellationRequested && (sleep -= 5) > 0)
        {
            Thread.Sleep(5);
        }
    }
}

答案 2 :(得分:0)

对于使用Framework .Net 4.0的用户,

我对接受的答案进行了调整,使其具有增强功能,因为TokenSource会被丢弃,并且每次调用Method(...)都会重新创建,因此可以随时重新启动。

Microsoft.Bcl.Async v1.0.168用于.NET Framework 4(带有KB2468871)

public CancellationTokenSource TokenSource = null;
...
await Method(TokenSource);
...

// Somewhere else, cancel the operation
TokenSource?.Cancel();
...
async void Method(CancellationTokenSource tokenSource)
{
    try
    {
        // Create a new CancellationTokenSource each time starting the new work stuff
        tokenSource = new CancellationTokenSource();

        foreach (var item in this)
        {
            if (!tokenSource.IsCancellationRequested)
            {
                // Do work stuff
                ...

                // Using await for async method to make UI responsive while waiting
                await Task.Factory.StartNew(() =>
                {
                    tokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(1000));
                });
            }
            else
                break;
        }
        finally
        {
            // Release the tokenSource to reuse a new one nex time method is called
            tokenSource.Dispose();
        }       
}

致谢。