在任务中包装一个呼叫,添加超时?

Wrap a call in a task, to add a timeout?

我们有一个从第 3 方使用的 SDK。我们根本无法访问或洞察代码,也无法用它更改任何内容。

我们 运行 遇到了一个问题,我们对 SDK 中的一个对象进行了一系列更新,然后当我们调用他们的 .Commit() 方法时,它就消失了,并且永远不会回来。他们的 Commit 没有超时参数或任何可以告诉它的东西 - 嘿,已经放弃了

因此,当他们的代码被遗忘时,我们的程序也会被遗忘。

我想知道是否有一种方法可以使用 async/await 东西实质上为对 Commit 的调用添加超时。不过,我之前没有做过任何异步操作,所以我不确定这是否可行。就我们程序的流程而言,我仍然需要它是同步的。

本质上,我正在设想一些类似

的东西
    ... <setting a bunch of sdkObject fields> ...

    var done = false;

    await new Task(function(ref sdkObject, ref done) {
            sdkObject.Commit();
            done = true;
        }, timeout: 60000);

    if (done) {
        <perform post-success code>
    } else {
        <perform post-failure code>
    }

这样我们就可以人为地在他们的 Commit 方法周围设置超时,这样即使它被遗忘,再也不会出现,我们的代码至少可以尝试优雅地结束并继续处理下一条记录。

I'm wondering if there is a way that I can use async/await stuff to essentially add a timeout to the call to their Commit.

嗯...有点。

您可以将调用包装到 Task.Run 中,然后使用 WaitAsync 创建可取消的等待,例如:

try {
  await Task.Run(() => sdkObject.Commit()).WaitAsync(TimeSpan.FromSeconds(60));
  <perform post-success code>
} catch (TimeoutException {
  <perform post-failure code>
}

但是,这可能无法按预期工作。 WaitAsync 为您提供了取消 wait 的方法 - 它没有为您提供取消 Commit 的方法。 Commit 将继续执行 - 只是您的应用程序不再关心它是否完成、何时完成或如何完成。

您正在使用的库可能喜欢也可能不喜欢在最后一个仍然是 运行 时调用 另一个 Commit。所以这实际上可能不适用于您的用例。

真正取消不可取消代码的唯一方法是将代码包装到一个单独的进程中,并在您想要强制取消时杀死该进程。这很复杂,但有时你别无选择。