Thread/Task cancellation

Ruby The Roobster michaeleverestc79 at gmail.com
Fri Jul 28 20:13:24 UTC 2023


On Friday, 28 July 2023 at 18:52:59 UTC, Ruby The Roobster wrote:
> On Friday, 28 July 2023 at 18:17:18 UTC, Gjiergji wrote:
>> I am coming from a C# background. I understood that there is 
>> no async/await equivalent in D (except fibers which are not 
>> suitable for multi threading), but if I am using threads, what 
>> is the D idiom to implement cancellation?
>>
>> Usually a long running thread looks like this (in C#):
>>
>> ```csharp
>> try
>> {
>>    while (!cancellationToken.IsCancellationRequested)
>>    {
>>       //do some work
>>       await SomethingAsync(cancellationToken);
>>       //do some other work
>>       await Task.Delay(TimeSpan.FromSeconds(5000), 
>> cancellationToken);
>>    }
>> }
>> catch (OperationCancelledException e) when (e.Token == 
>> cancellationToken)
>> {
>>    //someone cancelled any of the await calls above, we can 
>> swallow it or log it
>> }
>>
>> ```
>>
>> The question is how do I pass a `cancellationToken` to the 
>> calls from the loop in order to terminate them before 
>> completion. For example, I learnt about `Thread.sleep` in 
>> phobos, but I cannot pass a cancellation token in order to 
>> cancel it before the intended sleep duration.
>>
>> Thx.
>
> [SNIP]

> You could use a thread to check if the token has been sent via 
> message passing, and when it is sent, throw an exception, like 
> this:
>

>
> This does however, terminate with signal 11 upon sending the 
> terminate signal, and I'm not sure why.

Ignore my above code, Here is something that should work:

```d
import std.concurrency;

void foo()
{
     try
     {
         auto tid = spawnLinked(&bar);
         ownerTid.send(tid);
         // do stuff
         // ...

         auto c  = receiveTimeout(0.msecs, (ubyte a) {}); // Since 
bar is linked, this will throw an exception when bar terminates
     }
     catch(Exception e)
     {
         // Do whatever with the exception message, but it 
terminates the function execution.
     }
}

void bar()
{
     bool terminate = false;
     terminate = receiveOnly!bool();
}

void main()
{
     spawn(&foo);
     Tid tid = receiveOnly!Tid();
     // ...
     if(needsToTerminateFooForSomeReason)
         tid.send(true);
     // ...
}
```

This is the only way I could think of doing this, since 
exceptions don't travel up the threads.


More information about the Digitalmars-d-learn mailing list