快速提问,我正在执行一项任务,该任务会引发一些其他对象正在订阅的事件。有没有办法在执行中取消该对象的事件处理程序?试图使用取消令牌来做到这一点,
public event Action<Int> OnUpdate;
CancellationTokenSource cts = new CancellationTokenSource();
Task t = Task.Factory.StartNew(state => {
try {
var token = (CancellationToken)state;
token.ThrowIfCancellationRequested();
OnUpdate(_int);
} catch (Exception e) {
Console.WriteLine("Update threw exception : {0}", e.Message);
}
}, cts.Token, cts.Token);
if (!t.Wait(8000, cts.Token)) {
cts.Cancel();
Console.WriteLine("Update task did not finish in time.");
} else {
Console.WriteLine("Task did finish in time.");
}
这里的想法是我开始一个新任务t,它引发一个由外部对象捕获和处理的事件OnUpdate。我希望任务取消,如果它花了超过8秒来处理更新,这是取消令牌使用背后的想法。但是,即使我调用cts.Cancel(),外部事件处理程序仍然会运行完成。我有什么可以做的吗?
编辑 - 为了清楚,评论者指出,我仍然坚持使用Action,因为这是一个面向公众的API,我正在编辑。我可能会转而生成新的Thread而不是任务,然后调用Thread.Abort()但这看起来相当野蛮;我希望有一个更好的解决方案。
答案 0 :(得分:0)
不幸的是,int main()
{
int arr[14] = {0,0,0,0,0,4,4,4,4,5,5,5,7,9};
int last_non_duplicate_index = 0;
int current_index = 0;
int size = 14;
int new_size = size;
bool is_last_value = false;
// you can use for interchangeably
while(!is_last_value)
{
current_index++; // move one position ahead
if(current_index < size) // out of bonds check
{
if(arr[last_non_duplicate_index] != arr[current_index]) // value at position of current index is different
{
last_non_duplicate_index++; // increase index of the last value which was not a duplicate by one
arr[last_non_duplicate_index] = arr[current_index]; // write at that index
// e.g. if last index was 0 -> increase it to 1 and rewrite whatsever under arr[1] (current index)
}
else // values are the same
{
new_size--; // devrease the size
}
}
else
{
is_last_value = true; // current_index >= size -> out of bonds
}
}
for (int i = 0; i < new_size; i++)
{
std::cout << "arr[" << i << "]" << " = " << arr[i] << std::endl;
}
std::cout << "New size: " << new_size << std::endl;
return 0;
}
只有在实际观察到它时才能完成它的工作。从好的方面来说,这可以确保您的应用程序可以在从任务早期返回之前清理它的状态。但是,它要求任务中的代码主动与CancellationToken
进行交互。
如果您希望终止一个完全不受控制的事件处理程序,那么您将无法在一段时间后强制进行检查。
重要提示:如果您使用的是任务异步协议(TAP),请勿调用CancellationToken
。这是阻止您的应用程序执行任何操作的阻塞调用。您也可以直接调用处理程序并避免头痛。如果您不关心回调需要多长时间,并且您只是想在完成后做一些事情,那么正确的方法是使用Task.Wait()
/ async
。在这种情况下,解决方案将改为:
await