locked
Task management design guidance RRS feed

  • Question

  • I have some generic consumer/producer models I use in a Windows Service. While entitled to run by calling a method which receives a cancellation token, they open a using block on a cancellation token source and a linked cancellation token source then dispatch tasks as work arrives, roughly equating to:
    void Run(CancellationToken cancellationToken)
    {
        using (SemaphoreSlim semaphoreSlim = new SemaphoreSlim(3, 3))
        using (CancellationTokenSource cancellationTokenSourceFault = new CancellationTokenSource())
        using (CancellationTokenSource cancellationTokenSourceLinked = CancellationTokenSource.CreateLinkedTokenSource(
            cancellationTokenSourceFault.Token,
            cancellationToken))
        {
            while (!cancellationTokenSourceLinked.IsCancellationRequested)
            {
                // Block in exhausted semaphore while checking cancellationToken.
    
                // Dequeue work.
    
                // Create task with cancellationTokenSourceLinked as task cancellation.
    
                // If task faults, call cancellationTokenSourceFault.Cancel()
            }
    if (cancellationTokenSourceFault.IsCancellationRequested) { // Log and handle shutdown etc... } } }
    The question I have is on the disposed closures that the tasks leverage. If 3 tasks are active and one faults and signals exit, I leave the using blocks while potentially two others are running. I can remain in the using block if I keep track of the tasks and cancel the remaining active tasks. This of course requires concurrent collections so a task can remove itself in a continuation.

    Is that overhead worth it, or should I simply expect a potential ObjectDisposedException in the tasks continuation and end the continuation assuming termination is imminent?

    Thanks!

    • Edited by Ritmo2k Tuesday, November 22, 2016 7:52 PM
    Tuesday, November 22, 2016 6:55 PM

Answers

  • What I ended up doing if the fault cancellation source is set was to wait with a reasonable timeout for the semaphore to become full indicating all tasks have completed. This seems to be a reasonable balance between the overhead of keeping track of task instances or just the semaphore which indicates the same indirectly with far less work.

    Thanks.
    • Proposed as answer by DotNet Wang Thursday, December 1, 2016 1:26 AM
    • Marked as answer by Ritmo2k Thursday, December 1, 2016 9:36 AM
    Wednesday, November 30, 2016 11:42 PM

All replies

  • Hello,

     A question about the project tasking, is your app Task work

    associated with Local Sync resource utilization?

     

     Thanks :)

    Tuesday, November 22, 2016 11:03 PM
  • Yes, the semaphore is released in a finally block of a continuation. In this case, the exception thrown would migrate the continuation task to a faulted state. This only happens when the application has been requested to end so termination is immanent.

    That alone should warrant the increased complexity but I am open to opinion. There are no unmanaged resources that may be left nor any outproc interactions that may be affected. So in reality the question boils down to semantics on proper procedure.

    Thanks for the question, I am glad you prompted me to think about it this way.
    Tuesday, November 22, 2016 11:26 PM
  • Hi Ritmo2k,

    >>"Is that overhead worth it, or should I simply expect a potential ObjectDisposedException in the tasks continuation and end the continuation assuming termination is imminent?"

    I suggest you use the second way. Create a wrapper for each task and manage the CancellationToken and handle exception in each task.  It will reduce the complexity of the code and make the your application more scalable.

    Best Regards,
    Li Wang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, November 30, 2016 6:43 AM
  • What I ended up doing if the fault cancellation source is set was to wait with a reasonable timeout for the semaphore to become full indicating all tasks have completed. This seems to be a reasonable balance between the overhead of keeping track of task instances or just the semaphore which indicates the same indirectly with far less work.

    Thanks.
    • Proposed as answer by DotNet Wang Thursday, December 1, 2016 1:26 AM
    • Marked as answer by Ritmo2k Thursday, December 1, 2016 9:36 AM
    Wednesday, November 30, 2016 11:42 PM
  • Hi Ritmo2k,

    That's good. Thank you for sharing your solution. Please mark your solution as answer. In doing so, it will benefit all community members who are facing similar issues. Your contribution is highly appreciated.

    Best Regards,
    Li Wang


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, December 1, 2016 1:26 AM