【问题标题】:Stop Task on long running method在长时间运行的方法上停止任务
【发布时间】:2014-02-27 01:18:50
【问题描述】:

我有一个外部 dll,其中包含一些我需要调用的方法。另外,我希望能够为执行这些方法配置超时,以便在执行时间>配置超时时中止它们。 我在不同的任务上调用这些方法,如下所示:

Parallel.ForEach(....
{
    Func<object> asyncFucntion = () => DynamicCall(method, paramList);
    IAsyncResult ar = asyncFucntion.BeginInvoke(null, null);
    if (ar.AsyncWaitHandle.WaitOne(timeout, true))
    {
        return asyncFucntion.EndInvoke(ar);
    }
    else
    {
        //HERE I NEED to stop DynamicCall. Timeout was EXCEEDED
    }
});

现在,我可以获取 DynamicCall 线程 id 并中止它。还有其他方法吗?更轻松的方式?我无法使用取消令牌,因为我无法修改外部 Dll

谢谢, 亚历克斯

【问题讨论】:

  • 如果您需要突然停止操作 abort 是一种方法(除非您没有其他方法,否则不要这样做),否则请查看合作取消

标签: c# .net multithreading timeout abort


【解决方案1】:

中止线程(尤其是池线程)是really horrible thing 要做的事情。您可以考虑让每个asyncFunction 呼叫自然结束,而无需在超时的情况下观察其结果。见"How do I cancel non-cancelable async operations?"

附带说明,您在这里使用Parallel.ForEach 的效率非常低,该操作占用的线程大约是实际需要的两倍。如果没有Parallel.ForEach,它可能如下所示,这是一个更好的版本,IMO:

var tasks = methods.Select(method =>
{
    Func<object> asyncFunction = () => DynamicCall(method, paramList);

    var task = Task.Factory.FromAsync(
        (asyncCallback, state) => asyncFunction.BeginInvoke(asyncCallback, state),
        (asyncResult) => asyncFunction.EndInvoke(asyncResult), 
        null);

    return Task.WhenAny(task, Task.Delay(timeout)).Unwrap();
});

Task.WhenAll(tasks).Wait(); // or Task.WaitAll();

【讨论】:

  • 谢谢,第二部分我同意,我使用了两倍多的线程。但在第一部分,我真的需要关闭这些线程。有些可以持续长达 1 小时,最终会填满内存
  • 没问题。恐怕你也必须同意第一部分。 BeginInvoke 使用池线程,在池线程上调用 Abort 是一个非常糟糕的主意:stackoverflow.com/q/2335238/1768303
  • @AlexandruTata,您应该考虑使用辅助进程来托管您的 BeginInvoke 线程(单独的 EXE)。如果需要,您可以杀死它并重新启动它,这比在您自己的进程中杀死线程要好得多。
猜你喜欢
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2012-10-15
  • 2014-03-20
相关资源
最近更新 更多