在C#中取消/中止任务

时间:2016-11-22 19:58:04

标签: c# multithreading

我在C#中有一个程序可以进行一些服务调用。 我需要在这个程序中添加一些代码,以便在我点击一个按钮(winform)时能够停止这些服务调用[例如,如果调用太长而且用户感到无聊]。

困难在于我无法修改进行调用的代码块。

为了做到这一点,我计划用Unity Framework做一些拦截。 我想在每次输入服务调用代码块时创建一个Task。然后,如果用户单击我的按钮,则取消此任务。

我看过CancellationToken,但问题是我无法修改来电块,因此我无法if(ct.IsCancellationRequested)ct.ThrowIfCancellationRequested(); 同样适用于AutoResetEvent& ManualResetEvent的。 调用并不总是异步的,并且使用了cancelToken,因此我认为捕捉OperationCanceledException是不可能的。

我也看过使用Threads并做了一些Thread.Abort(),但这种方法似乎每次有人都会杀死小狗。

以下是我当前程序的示例(拦截尚未实现,我想先在一次调用中测试它):

private void Test()
{
    Task.Factory.StartNew(MyServiceCallFunction); // How to cancel the task when I press a button ?
}

// Can't touch the inside of this function :
private void MyServiceCallFunction()
{
    // Blabla I prepare the datas for the call
    // Blabla I do the call
}

我该怎么做? (我没有义务使用任务)

谢谢,

2 个答案:

答案 0 :(得分:2)

"正确"这样做的方法是使用CancellationTokens,但由于你无法修改正在运行的代码,唯一的另一种方法是杀死小狗并使用Thread.Abort()

类似的东西:

Thread t;
Task.Factory.StartNew(() =>
    {
        t = Thread.CurrentThread;
        MyServiceCallFunction();
    });

t.Abort();

答案 1 :(得分:-1)

非常有趣的问题。当第三方通话正在进行TPL时,你当然无能为力;在你的情况下,它是MyServiceCallFunction()。

我一直处于类似的情况,这篇博文对我有帮助:https://social.msdn.microsoft.com/Forums/vstudio/en-US/d0bcb415-fb1e-42e4-90f8-c43a088537fb/aborting-a-long-running-task-in-tpl?forum=parallelextensions

(阅读:Stephen Toub - MSFTMicrosoft(MSFT)评论)

他提到了这个解决方案:

int Test(CancellationToken token)
    {
        Thread currentThread = Thread.CurrentThread;
        using (token.Register(currentThread.Abort))
        {
            MyServiceCallFunction()
        }
    }

还用Task.Run(...)替换Task.Factory.StartNew(...);同样,感染后者更强,但更易读。