使用可能挂起的 API 强制取消任务

2024-03-10

我目前正在使用串行端口,并且我使用的 API 有时会挂在读取上,即使设置了自己的超时也是如此。

这不是一个大问题,但是当发生这种情况并且挂起的线程需要关闭时我需要做一些工作。我已经尝试过以下操作,但它一直给我带来问题,因为 API 调用没有终止,而是允许在其余代码继续时继续,并且TimeoutException被扔了。我该如何使用Task是否能够在一段时间后取消挂起的任务?

CancellationToken token = new CancellationToken();
var task = Task.Factory.StartNew(() => 
           {
               CallingAPIThatMightHang(); // Example
           }, token);

if (!task.Wait(this.TimeToTimeOut, token))
{
    throw new TimeoutException("The operation timed out");
}

CancellationToken是合作取消的形式。您需要在执行操作时调整令牌,并观察是否请求取消。

从您的代码块来看,您似乎有一个长时间运行的同步操作,您将其卸载到线程池线程。如果是这种情况,请查看是否可以将该串行调用分离为块,这样您可以在读取块后轮询令牌。如果你can't,将无法取消。

请注意,为了请求取消,您必须创建一个CancellationTokenSource,稍后您可以将其称为Cancel() method.

附带说明一下,串行端口是异步 IO,您可以自然地使用异步 API,而不是将同步卸载到线程池线程。

Edit:

@HansPassant 给出了一个更好的主意。在另一个进程(您保留引用的进程)内运行第三方调用。一旦需要终止它,请终止该进程。

例如:

void Main()
{
    SomeMethodThatDoesStuff();
}

void SomeMethodThatDoesStuff()
{
   // Do actual stuff
}

然后在单独的进程中启动它:

private Process processThatDoesStuff;

void Main()
{
    processThatDoesStuff = Process.Start(@"SomeLocation");
    // Do your checks here.

    if (someCondition == null)
    {
        processThatDoesStuff.Kill();
    }
}

如果您需要在这两个进程之间传达任何结果,可以通过多种机制来实现。一种方法是写入和读取进程的标准输出。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用可能挂起的 API 强制取消任务 的相关文章

随机推荐