HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Abort thread on new request, but complete only last request

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lastnewbutrequestabortcompletethreadonly

Problem

The situation is that a certain asynchronous operation is called multiple times, which is basically to consolidate results. But I want to abort every time a new request comes in, which means that only the last call will run completely. Does this solution look reasonable?

I have tried replicating the process in a test program, where the for loop represents 'x' number of calls generated for consolidation. But because we only need to run calculation once, we can safely run it on the last call.

I am creating a new thread each time, and cancelling the previous ones if there are any. This seems to work, but is there a better way or can this be improved?

```
static void Main(string[] args)
{
var listCancellationTokens = new List();

for (var i = 1; i c.Cancel());

CreateThread(cancelSource);

listCancellationTokens.Add(cancelSource);
}
}

private static void CreateThread(CancellationTokenSource cancellationTokenSource)
{
new Thread(() =>
{
try
{
ConsolidateResults(cancellationTokenSource.Token);
}
catch
{
;
}
}).Start();

}

private static void ConsolidateResults(CancellationToken cancelToken)
{
UpdateValues();
if (cancelToken.IsCancellationRequested)
{
return;
}
TurnOffEvents();
if (cancelToken.IsCancellationRequested)
{
return;
}
GetMarginPercentage();

if (cancelToken.IsCancellationRequested)
{
return;
}
TurnOnEvents();
}

//This is how it is done at the moment
private void Commit(bool adjustDiscount = false)
{
lock (_updateRunnerLock)
{
_updateRunnerRemainingCycles = 40;
if (_updateRunner == null)
{
_updateRunner = new Thread(UpdateRunner);
_updateRunner.Start();
}
}
}

private void UpdateRunner()
{
while (_updateRunnerRemainingCycles > 0)
{
Thread.Sleep(500);
_updateRunnerRemainingCycle

Solution

Basically it is in its current state senseless to have a

var listCancellationTokens = new List();


if all you want is one running thread at any time.

So what I suggest instead is to create one Task and if there comes the situation that this task should be canceled you should cancel the task and Wait until the task returned.

After the Task returned you then create the new Task.

private static Task task;
private static CancellationTokenSource cancelSource;
static void Main(string[] args)
{

    for (var i = 1; i  ConsolidateResults(cancelSource.Token));

    }
    Console.ReadLine();
}


then you should change the ConsolidateResults() method to

private static void ConsolidateResults(CancellationToken cancelToken)
{
    cancelToken.ThrowIfCancellationRequested();

    UpdateValues();
    TurnOffEvents();
    GetMarginPercentage();
    TurnOnEvents();
}

Code Snippets

var listCancellationTokens = new List<CancellationTokenSource>();
private static Task task;
private static CancellationTokenSource cancelSource;
static void Main(string[] args)
{

    for (var i = 1; i <= 5; i++)
    {
        if(task != null && (!task.IsCompleted || !task.IsFaulted))
        {

            try 
            {
                cancelSource.Cancel();
                task.Wait(cancelSource.Token);
            }
            catch (OperationCanceledException ex) 
            { 
                //swallow because by using ThrowIfCancellationRequested() 
                //in combination with cancelSource.Cancel() an exception is thrown.
            }
        }
        cancelSource = new CancellationTokenSource();

        task = Task.Factory.StartNew(() => ConsolidateResults(cancelSource.Token));

    }
    Console.ReadLine();
}
private static void ConsolidateResults(CancellationToken cancelToken)
{
    cancelToken.ThrowIfCancellationRequested();

    UpdateValues();
    TurnOffEvents();
    GetMarginPercentage();
    TurnOnEvents();
}

Context

StackExchange Code Review Q#103763, answer score: 6

Revisions (0)

No revisions yet.