简体   繁体   中英

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 . 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 ?

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.

You can use Task.Delay which also can be canceled.

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,

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(...) .

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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