简体   繁体   English

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

[英]best way to exit Thread.Sleep in the middle

i have some operation that sometimes i want to stop in the middle:我有一些操作,有时我想在中间停下来:

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

The issue here that inside this foreach sometimes i need specific delay time so i am using Thread.Sleep .这里的问题是在这个foreach有时我需要特定的延迟时间,所以我使用Thread.Sleep So when i stop my operation in case i am still inside this Thread.Sleep my application is waiting until this Thread.Sleep end and only than stop my operation so can i exit from Thread.Sleep in the middle ?所以当我停止我的操作,以防我仍然在这个Thread.Sleep我的应用程序正在等待这个Thread.Sleep结束,然后停止我的操作,所以我可以在中间退出Thread.Sleep吗?

Update更新

The reason i need specific sleep is because i am play packets and between every packets there is a Time stamp so this is why i need this sleep.我需要特定睡眠的原因是因为我正在播放数据包,并且每个数据包之间都有一个Time stamp所以这就是我需要此睡眠的原因。

You can use Task.Delay which also can be canceled.您可以使用也可以取消的 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
    }
}

When you want to call当你想打电话时

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

And when you want to cancel.当你想取消时。

source.Cancel();

For those who are using Framework .Net 4.0,对于那些使用 Framework .Net 4.0 的人,

I've adapted the accepted answer with the enhancement that, it can be restarted any times because TokenSource is discarded and recreated for each call to Method(...) .我已经通过增强修改了接受的答案,它可以随时重新启动,因为每次调用Method(...)都会丢弃并重新创建TokenSource

Using Microsoft.Bcl.Async v1.0.168 for .NET Framework 4 (with KB2468871)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();
        }       
}

Regards.问候。

One possible solution could be to use your own Sleep method like (needs to be improved for sure!):一种可能的解决方案是使用您自己的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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM