Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Deadlocks are definitely hard to spot, but this may be the problem. In your code, I didn't see that you added any timeout to the enqueue, peek or dequeue - which means it will take the default of Infinite.</p> <p>The enqueue has this line in it - meaning, like any synchronization object, it will block until either the Enter completes (it locks the monitor) or the Timeout occurs (since you don't have a timeout, it will wait forever)</p> <pre><code>TSimpleThreadedQueue.Enqueue(const Item: T; Timeout: LongWord): TWaitResult; ... if not TMonitor.Enter(FQueue, Timeout) </code></pre> <p>I'm also going to make the assumption that you implemented PEEK yourself based on the Dequeue - only you don't actually remove the item.</p> <p>That appears to implement its own timeout - however, you still have the following:</p> <pre><code>function TSimpleThreadedQueue.Peek/Dequeue(var Item: T; Timeout: LongWord): TWaitResult; ... if not TMonitor.Enter(FQueue, Timeout) </code></pre> <p>Where timeout is Infinite - so, if you are in the peek method waiting for it to be signaled with an infinite timeout, then you can't Enqueue something from a second thread without blocking that thread waiting for the peek method to become complete on an infinite timeout.</p> <p>Here is a snippet of the comment from TMonitor</p> <pre><code>Enter locks the monitor object with an optional timeout (in ms) value. Enter without a timeout will wait until the lock is obtained. If the procedure returns it can be assumed that the lock was acquired. Enter with a timeout will return a boolean status indicating whether or not the lock was obtained (True) or the attempt timed out prior to acquire the lock (False). Calling Enter with an INFINITE timeout is the same as calling Enter without a timeout. </code></pre> <p>Since the implementation uses Infinite by default, and a TMonitor.Spinlock value is not provided, that will block the thread until it can acquire the FQueue object.</p> <p>My suggestion would be to change your code as follows:</p> <pre><code> // Use Peek instead of Dequeue, because the item should not be removed from the queue if it fails while true do case fQueue.Peek(fCurrentFile,10) wrSignaled: try if UploadFile(fCurrentFile) = '' then begin fQueue.Dequeue(Temp); // Delete the item from the queue if succesful SignalComplete; end; except on E: Exception do SignalError(E.Message); end; wrTimeout: sleep(10); wrIOCompletion, wrAbandoned, wrError: break; end; //case </code></pre> <p>This way, peek won't hold the lock on FQueue indefinitely, leaving a window for the Enqueue to acquire it and add the file from the main (UI) thread.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload