Note that there are some explanatory texts on larger screens.

plurals
  1. PORace condition with CancellationToken where CancellationTokenSource is only cancelled on the main thread
    primarykey
    data
    text
    <p>Consider a Winforms application, where we have a button that generates some results. If the user presses the button a second time, it should cancel the first request to generate results and start a new one. </p> <p>We're using the below pattern, but we are unsure if some of the code is necessary to prevent a race condition (see the commented out lines).</p> <pre><code> private CancellationTokenSource m_cts; private void generateResultsButton_Click(object sender, EventArgs e) { // Cancel the current generation of results if necessary if (m_cts != null) m_cts.Cancel(); m_cts = new CancellationTokenSource(); CancellationToken ct = m_cts.Token; // **Edit** Clearing out the label m_label.Text = String.Empty; // **Edit** Task&lt;int&gt; task = Task.Run(() =&gt; { // Code here to generate results. return 0; }, ct); task.ContinueWith(t =&gt; { // Is this code necessary to prevent a race condition? // if (ct.IsCancellationRequested) // return; int result = t.Result; m_label.Text = result.ToString(); }, ct, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext()); } </code></pre> <p>Notice:</p> <ul> <li>We only ever cancel the <code>CancellationTokenSource</code> on the main thread.</li> <li>We use the same <code>CancellationToken</code> in the continuation as we do in the original task.</li> </ul> <p>We're wondering whether or not the following sequence of events is possible:</p> <ol> <li>User clicks "generate results" button. Initial task t1 is started.</li> <li>User clicks "generate results" button again. Windows message is posted to queue, but the handler hasn't been executed yet.</li> <li>Task t1 finishes.</li> <li>TPL <strike>starts</strike> <em>prepares to start</em> the continuation (since the <code>CancellationToken</code> is not cancelled yet). The task scheduler posts the work to the Windows message queue (to get it to run on the main thread).</li> <li>The generateResultsButton_Click for the 2nd click starts executing and the <code>CancellationTokenSource</code> is cancelled.</li> <li>The continuations work starts and it operates as though the token were not cancelled (i.e. it displays its results in the UI).</li> </ol> <p>So, I think the question boils down to:</p> <p>When work is posted to the main thread (by using <code>TaskScheduler.FromCurrentSynchronizationContext()</code>) does the TPL check the <code>CancellationToken</code> on the main thread before executing the task's action, or does it check the cancellation token on whatever thread it happens to be on, and then post the work to the <code>SynchronizationContext</code>?</p>
    singulars
    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.
 

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