取消在任务中引发的外部事件处理程序

时间:2016-06-01 15:56:48

标签: c#

快速提问,我正在执行一项任务,该任务会引发一些其他对象正在订阅的事件。有没有办法在执行中取消该对象的事件处理程序?试图使用取消令牌来做到这一点,

                    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()但这看起来相当野蛮;我希望有一个更好的解决方案。

1 个答案:

答案 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