When deleting a job it didn't kill the worker thread even passing CancelationToken as parameter.
How to stop a long running thread?
Do you call the ThrowIfCancellationRequested method inside your method?
@odinserj Following examples I didn't find any solution of cancelling a task without a loop.
I did a task (I call as plugin) which executes SSIS package (ETL) and lasts at least for 3h. Sometimes I need to simply stop its processing. How can I call ThrowIfCancellationRequested when the method is waiting for the response? It's like the same as Thread.Sleep().
Piece of code
``` C#
protected override void Execute()
{
var eventListener = new SqlPackageEventListener();
eventListener.OnPackageVerbose += OnPackageVerbose;
var app = new Application();
var pkg = app.LoadPackage(PackageLocation, eventListener);
//Below is the synchronous execution of SSIS package and lasts the necessary time of each package
var pkgResults = pkg.Execute(null, null, eventListener, null, null);
if (pkgResults != DTSExecResult.Success)
throw new Exception(eventListener.Error);
Log.Info("The package executed successfully.");
}
```
How to cancel this method, keeping the safety in mind?
reading few docs on stackoverflow on how to make a sync method to act as async I could realize that's "simple" and possible.
So I'll start over again and try to make that job be async. My initial questions are:
IJobCancellationToken as parameter?ThrowIfCancellationRequested before or after the Execute?``` C#
//Entry method
public void Run(IJobCancellationToken ct)
{
Log.Info("Starting execution of {0}", Name);
try
{
//ct.ThrowIfCancellationRequested();
Execute();
}
catch (OperationCanceledException)
{
Log.Error("Cancellation requested, exiting...");
throw;
}
catch (Exception ex)
{
Log.Error(ex);
throw;
}
finally
{
Log.Info("Finishing execution of {0}", Name);
}
}
protected override void Execute()
{
var eventListener = new SqlPackageEventListener();
eventListener.OnPackageVerbose += OnPackageVerbose;
var app = new Application();
var pkg = app.LoadPackage(PackageLocation, eventListener);
var pkgResults = pkg.Execute(null, null, eventListener, null, null);
if (pkgResults != DTSExecResult.Success)
throw new Exception(eventListener.Error);
Log.Info("The package executed successfully.");
}
```

Is there pkg.ExecuteAsync method that takes a CancellationToken instance? Without this the only way to stop the method execution is to abort the whole thread. Thread.Abort method call is very dangerous.
Unfortunately there's no async method implemented. I'm using Microsoft.SqlServer.Dts.Runtime based on 2008 R2 (https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dts.runtime(v=sql.105).aspx)
Do you see another way of doing it?
I know that Thread.Abort is not a good idea at all.
If we forget about Hangfire, how would you cancel the execution of this method?
Simply aborting the thread. Even though it's not safe (as said) but in my production environment sometimes is mandatory.
The question is : How can I call to abort the thread when deleting a processing job?
You can start a new thread in your method, and call the pkg.Execute method in that thread. After starting a thread, you can wait for the thread completion together with polling the IJobCancellationToken instance (with delays to not to stress the storage). If it throws, then abort the thread and rethrow the exception.
// Pseudocode, just to show the intention
var thread = new Thread(Execute);
thread.Start();
while (!thread.Join(TimeSpan.FromSeconds(1)))
{
try
{
token.ThrowIfCancellationRequested();
}
catch (OperationCanceledException)
{
thread.Abort();
throw;
}
}
I don't like to teach Hangfire how to abort threads, because it is not a correct way of doing things. In your case, Thread.Abort is fine, in other cases it is not.
It is very strange that DTS API doesn't take any CancellationToken instances to be able to cancel a query.
I'm not sure what you're doing in the package, but can the package be broken up into (much) smaller parts and run it batches ? That way you can check the cancellation token between batches.
@yangman The package actually is a SSIS package (ETL) that executes various sql instructions. There's no way at this time of breaking up in smaller ones.
There's a IDTSEvents.OnQueryCancel event, which is raised periodically to determine if package execution should be cancelled.
You should subscribe to that event and return cancellationToken.IsCancellationRequested value.