I am trying to fix asynchronous C # code that starts a canceled operation performed in an external dll written in an unmanaged C ++ routine.
Is there a way to cancel a task using the Token Token passed to Task when it is created if the user delegates calls to an external uncontrolled C ++ procedure?
As far as I know, canceling a task involves a collaboration between the user delegate and the code that requested the cancellation. A successful cancellation includes a requesting code that calls the CancellationTokenSource.Cancel method, and a user delegate who completes the operation in a timely manner, or simply returning from the delegate when he notices that the cancellation request was raised (by polling the CancellationToken.IsCancellationRequested method) or by throwing an exception OperationCanceledException operations using the CancellationToken.ThrowIfCancellationRequested method. (cf http://msdn.microsoft.com/en-us/library/dd997396%28v=vs.110%29.aspx )
These two methods include the fact that the uncontrolled C ++ routine executed by the user delegate interacts by receiving the CancellationToken as a parameter and by regularly calling its IsCancellationRequested and / or ThrowIfCancellationRequested methods.
Is it possible to do this from an uncontrolled external C ++ procedure?
If not, is there a way to forcefully complete a task delegating a user (running an uncontrolled C ++ routine) when a cancellation request is requested by the requesting code?
Here is an example (extraction) of mixed C # / C ++ Cli / Unmanaged C ++ code that I am trying to fix in order to cancel the operation performed by a user delegate in the unmanaged part of C ++ code:
FrmDemo.cs: ------------------------------------------- --- ---------------------------
public class FrmDemo : Form
{
private CliClass m_CliObject;
private System.Threading.CancellationTokenSource m_Cts;
private System.Threading.CancellationToken m_Ct;
private void FrmDemo_Load(object sender, EventArgs e)
{
this.m_CliObject = new NSDemo.CliClass();
...
}
private async void btnStart_Click(object sender, EventArgs e)
{
m_Cts = new System.Threading.CancellationTokenSource();
m_Ct = m_Cts.Token;
await Task.Factory.StartNew(() =>
{
this.m_CliObject.DoSomething();
}, m_ct);
...
}
private void btnCancel_Click(object sender, EventArgs e)
{
m_Cts.Cancel();
}
CliClass.h: ------------------------------------------- ----------
#include "DemoCore.h"
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace cli;
namespace NSDemo
{
public ref class CliClass
{
public:
CliClass();
~CliClass();
void DoSomething()
{
_coreObject->DoSomething();
}
private:
UNSDemo::CoreClass *_coreObject;
bool _disposed;
};
}
CliClass.cpp: ------------------------------------------
namespace NSDemo
{
CliClass::CliClass()
{
_coreObject = new UNSDemo::CoreClass(...);
....
}
CliClass::~CliClass()
{
if (_disposed)
return;
if (_coreObject != nullptr) {
delete _coreObject;
_coreObject = nullptr;
}
_disposed = true;
GC::SuppressFinalize(this);
}
CoreClass.h-----------------------------------------------------------------
namespace UNSDemo {
class __declspec(dllexport) CoreClass {
public:
ScanningCore();
~ScanningCore();
void DoSomething();
private:
...
};
}
CoreClass.cpp: ------------------------------------------- ---------------------------------
#include "CoreClass.h"
namespace UNSDemo {
CoreClass::CoreClass()
{
...
}
CoreClass::~CoreClass()
{
...
}
void CoreClass::DoSomething()
{
while (...) {
...
}
}
}
.