Home > Enterprise >  Is there a way to reuse the same thread?
Is there a way to reuse the same thread?

Time:09-11

var a = 3
var b= 5
for (int i = 0; i < 10; i  )
{
    var c = a   b;
    Console.WriteLine(c); //This line should execute on another thread
}

How could I make the value of c print on another thread, without making a new thread each iteration? The reason I want to make it run on another thread is because writing the value of c would block the thread and make the script slower. Basically its for visual feedback

Note: I cant put a loop in the thread since the thread is only supposed to run after c is calculated

CodePudding user response:

I think you need a standard Publisher/Consumer approach.

using System.Threading.Channels;

Channel<int> channel = Channel.CreateUnbounded<int>();
ChannelWriter<int> writer = channel.Writer;
ChannelReader<int> reader = channel.Reader;

var task = Task.Run(async () => await Consume());

var a = 3;
var b = 5;
for (int i = 0; i < 10; i  )
{
    var c = a   b   i;
    await writer.WriteAsync(c);
}
writer.Complete();

await task; // or Console.ReadKey();

async Task Consume()
{
    await foreach (int x in reader.ReadAllAsync())
    {
        Console.WriteLine(x);
    }
}

The part of the code that publishes data to the channel can also be executed in a separate thread, if necessary.

CodePudding user response:

Based on the information you have given, a possible solution would be the following:

int sum = 0;
object lockObj = new object();

var tokenSource2 = new CancellationTokenSource(); 
CancellationToken ct = tokenSource2.Token;

void Progress()
{
    while (true)
    {
        // We should lock only if writting to the sum var but this is just an example.
        lock (lockObj)
        {
            Console.WriteLine(sum);
        }
        // Just simple wait in order to not write constantly to the console.
        Thread.Sleep(100);
        // If process canceled (finished), then exit.
        if (ct.IsCancellationRequested)
            return;
    }
}

var a = 3;
var b = 5;

Task? t = null;
for (int i = 0; i < 100000; i  )
{
    // Lock to be sure that there is no concurrency issue with the Progress method if it writes to the variable.
    // In our case it shouldn't be required as it only reads.
    lock (lockObj)
    {
        sum = a   b;
    }
    if (t == null)
        t = Task.Run(() => Progress());
}
tokenSource2.Cancel();

t.Wait();

Things to note:

  1. We lock the access of the sum variable although it is not required as we only read from it. You can safely remove the lock statements if you do not intent to write to it from the background thread.
  2. We use a cancellation token to indicate the termination of the thread that does the calculation (in our case the main thread). This way the other thread will terminate correctly and it will not end up running an endless loop.
  3. We use a Task.Wait() after we end our calculation. If we don't do it, the console app will instantly kill the background thread and we might not get results displayed on the screen.
  •  Tags:  
  • c#
  • Related