我正在尝试修复C#异步代码,以启动在未经管理的C++例程中执行的可取消操作的外部dll。
如果用户委托调用外部非托管C++例程,是否有一种方法可以使用传递给任务的取消令牌取消任务?
据我所知,任务取消涉及用户委托和请求取消的代码之间的协作。成功的取消涉及请求代码调用CancellationTokenSource.Cancel方法,并且用户委托通过简单地从委托返回或使用CancellationToken.ThrowIfCancellationRequested方法抛出OperationCanceledException,及时终止操作,当他注意到取消请求已被发出(通过轮询CancellationToken.IsCancellationRequested方法)。 (参见http://msdn.microsoft.com/en-us/library/dd997396%28v=vs.110%29.aspx)
这两种方式都涉及由用户委托执行的非托管C++例程通过将CancellationToken作为参数接收并定期调用其IsCancellationRequested和/或ThrowIfCancellationRequested方法来合作。
从非托管外部C++例程中是否可能实现这一点?
如果不行,是否有一种方法可以在请求代码请求取消时强制终止执行用户委托(执行非托管C++例程)的任务?
以下是我试图修复的混合C# / C++Cli /非托管C++代码的示例(摘录):
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)
{
// Creating the external CliObject:
this.m_CliObject = new NSDemo.CliClass();
...
}
// Event handler of the button starting the cancelable asynchrone operation:
private async void btnStart_Click(object sender, EventArgs e)
{
m_Cts = new System.Threading.CancellationTokenSource();
m_Ct = m_Cts.Token;
await Task.Factory.StartNew(() =>
{
// Launching a cancelable operation performed by a managed C++Cli Object :
this.m_CliObject.DoSomething(); // How to eventually pass the CancellationToken m_ct to the m_CliObject ?
}, m_ct);
...
}
//Event handler of the cancel button:
private void btnCancel_Click(object sender, EventArgs e)
{
// Requesting cancellation:
m_Cts.Cancel();
// (Or alternatively, how to eventually force the termination of the async Task without collaboration from it ?)
}
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()
{
// Performing the operation in the unmanaged coreObject:
_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()
{
...
}
// Method actually performing the cancelable operation:
void CoreClass::DoSomething()
{
// Main loop of the unmanaged cancelable operation:
while (...) {
...
// How to check the cancellation request from here ? (How to access the CancellationToken ?)
// and if cancellation is requested, how to eventually throw the OperationCanceledException ?
}
}
}
感谢您的帮助。