patterncsharpMinor
Abort thread on new request, but complete only last request
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
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
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
if all you want is one running thread at any time.
So what I suggest instead is to create one
After the
then you should change the
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.