0

I am writing an console application where I want to offload some CPU-bound work onto a new thread in order to keep the main thread responsive. However, I only want to create one new thread at a time; if more CPU-bound work is requested while some is still ongoing, that task should get queued. Here's my implementation:

    readonly ConcurrentQueue<Task> _searchQueue = new ConcurrentQueue<Task>();
    volatile bool _searchInProgress = false;

        var searchTask = new Task(() =>
        {
            // ... do some cpu-bound work ...

            // run the next task if one is queued

            if (_searchQueue.TryDequeue(out var nextTask))
            {
                nextTask.Start();
            }
            else
            {
                _searchInProgress = false;
            }
        });

        // *** attempt to propogate exceptions to the main thread ***

        searchTask = searchTask.ContinueWith(t =>
        {
            if (t.IsFaulted) throw t.Exception;
        });

        if (!_searchInProgress)
        {
            _searchInProgress = true;
            searchTask.Start();
        }
        else _searchQueue.Enqueue(searchTask);

This code worked fine before I added the ContinueWith clause. After I added it, I got the error:

Start may not be called on a continuation task.

A related SO question says to use Task.Factory.StartNew instead of the Task constructor, but this doesn't work for my use case since I want to create the Task but may not want to immediately start it.

James Ko
  • 32,215
  • 30
  • 128
  • 239
  • 1
    The SO question isn’t right either. The [documentation](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskfactory.startnew) clearly states to use Task.Run. Regarding your initial question: just call Start on the original task, where the continuation is attached to. The continuation will still run. So in your case omit the assignment to `searchTask` and just do `searchTask.ContinueWith(…)`. – ckuri Jun 28 '20 at 22:34
  • There is at least one race condition in your code, between the lines `_searchQueue.TryDequeue` and `_searchInProgress = false`. Are you interested in a robust solution, or you just want to fix the specific error message that you get? – Theodor Zoulias Jun 29 '20 at 00:18
  • @TheodorZoulias Any solution is fine as long as it also answers the original question. – James Ko Jun 29 '20 at 02:23
  • OK James. Sorry for not being interested in the question about the `Start` method not supported for continuation tasks. Attempting to answer it looks like a waste of time to me. If you are interested in a three-liner that solves robustly the problem of exclusive execution of CPU-bound tasks, let me know. :-) – Theodor Zoulias Jun 29 '20 at 07:20

0 Answers0