Would looping Thread.Sleep() be bad for performanc

2020-02-11 05:06发布

问题:

There is (or there has been) a lot of talk about wether it's good or bad to use the Thread.Sleep() method. From what I understand it is mainly to be used for debugging purposes.

Now I wonder: is it bad to use for my specific purpose, that is, constantly looping it to be able to pause/resume the thread? I do this because I want to pause a thread that performs I/O operations and be able to resume it in a simple way.

The I/O operations are basically just writing blocks of 4096 bytes to a file until all the data has been written to it. Since the file might be large and take a long time I want to be able to pause the operation (in case it would start eating much system resources).

My code, VB.NET version:

'Class level.
Private BytesWritten As Long = 0
Private Pause As Boolean = False

'Method (thread) level.
While BytesWritten < [target file size]
    ...write 4096 byte buffer to file...

    While Pause = True
        Thread.Sleep(250)
    End While

    ...do some more stuff...
End While

C# equivalent:

//Class level.
long bytesWritten = 0;
bool pause = false;

//Method (thread) level.
while(bytesWritten < [target file size]) {
    ...write 4096 byte buffer to file...

    while(pause == true) {
        Thread.Sleep(250);
    }

    ...do some more stuff...
}

I have heard about ResetEvents and I know a little bit about what they do, but I have never really looked much into them.

回答1:

I think, based on the description, I'd do this

'Class level.
Private BytesWritten As Long = 0
Private NotPaused As New Threading.ManualResetEvent(True)

The change in the variable name is fitting since this is how it would be used

    'Method (thread) level.
     While BytesWritten < [target file size]
        '...write 4096 byte buffer to file...

        NotPaused.WaitOne(-1)

        '...do some more stuff...
    End While

To make the loop pause do this

    NotPaused.Reset()

and to continue

    NotPaused.Set()


回答2:

In .NET there’s no reason to use Thread.Sleep besides trying to simulate lengthy operations while testing and / or debugging on an MTA thread as it will block.

Perhaps another option would be to use the TPL. Since you don't want to block you can use Task.Delay. As you probably know, a Task represents an asynchronous operation.



回答3:

I think that the more elegant way is to make the thread sleep indefinitely until it's awoken by another thread calling Thread.Interrupt on the first thread that's sleeping. There's a good example of this on with example code: Pausing and Resuming Threads.



回答4:

I might be misunderstanding what you're trying to achieve here, but from what I see, it seems like you're trying to block a thread until an IO task has finished. Semaphores would be the best bet here, instead of doing Thread.Sleep().

Most operating systems offer blocking semaphores that put a thread to sleep permanently until another thread wakes it up. You're probably better off utilizing them instead of constantly doing that check yourself.

Both Thread.Sleep() and blocking semaphores put the thread to sleep, but the latter does it perpetually until the resource has been freed (the semaphore has been signed). The former requires the thread to constantly wake up, check, and go back to sleep. The latter saves these execution cycles.