2

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.

david hol
  • 1,272
  • 7
  • 22
  • 44
  • 1
    _Why_ do you need a specific delay time? And do you realize that `Thread.Sleep` _cannot_ be used for reliable timing? Outside of very rare scenarios, you shouldn't use `Thread.Sleep`. – xxbbcc Nov 22 '15 at 15:16
  • So what you suggest ? – david hol Nov 22 '15 at 15:18
  • I don't know what you're trying to do. It's incredibly unlikely that `Thread.Sleep` would correctly solve whatever problem you're trying to solve but I can't recommend anything until you describe what you're trying to achieve. Right now, your question seems like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – xxbbcc Nov 22 '15 at 15:20
  • See my update please. – david hol Nov 22 '15 at 15:22
  • 1
    i think what you need is Task.Delay() which also can be canceled – M.kazem Akhgary Nov 22 '15 at 15:22
  • 1
    @davidhol Your edit doesn't add any useful detail to your question. I suggest you sit down and think through exactly what you're trying to do and how to solve it. You shouldn't be writing any multithreaded code if you don't clearly understand the difference between `Monitor` and `Thread.Sleep` (your comment suggests you don't). I'm not trying to be rude to you but writing correct multithreaded code is not easy. – xxbbcc Nov 22 '15 at 15:27
  • OK i will, BTW the @M.kazem Akhgary answer helps, you think this is good approach ? – david hol Nov 22 '15 at 15:45
  • Yes, @M.kazemAkhgary's is a reasonably good answer, if that's what you need. – xxbbcc Nov 22 '15 at 15:51
  • Fine, i also saw that CancellationTokenSource implement Dispose so i need to use it inside my foreach ? – david hol Nov 22 '15 at 15:53
  • Related: [How to “sleep” until timeout or cancellation is requested in .NET 4.0](https://stackoverflow.com/questions/18715099/how-to-sleep-until-timeout-or-cancellation-is-requested-in-net-4-0) – Theodor Zoulias May 13 '20 at 12:26
  • Also related: [Interrupt a sleeping Thread](https://stackoverflow.com/questions/7448589/interrupt-a-sleeping-thread) – Theodor Zoulias May 13 '20 at 12:58

3 Answers3

7

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();
M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • And what about after the cancel ? how to start it back ? i need to create this object again ? (new CancellationTokenSource...) – david hol Nov 22 '15 at 15:51
  • 2
    @davidhol you have to create new one. it is also answered here. http://stackoverflow.com/a/9332634/4767498 – M.kazem Akhgary Nov 22 '15 at 16:28
  • 1
    @M.kazem Akhgary, `Task.Delay` isn't available in .Net 4.0. Is there an alternative ? –  May 13 '20 at 09:37
0

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.

-1

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);
        }
    }
}
Markus Safar
  • 6,324
  • 5
  • 28
  • 44