0

我已经根据我在不同地方看到的东西创建了一个超时功能,但我很确定我做得不是很好!(但它似乎确实有效。)

我正在连接一个硬件,如果工作在几秒钟内连接,但如果不是,则需要大约 1 分钟才能超时。因此,如果我可以创建自己的超时功能,我可以将其设置为 20 秒,从而节省大量时间和等待时间。

我试图做到这一点,所以我的超时返回一个字符串:

static string CallWithTimeout(Action action, int timeoutMilliseconds)
{
    string reply = "";
    Thread threadToKill = null;
    Action wrappedAction = () =>
    {
        threadToKill = Thread.CurrentThread;
        action();
    };

    IAsyncResult result = wrappedAction.BeginInvoke(null, null);
    if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
    {
        reply = "Connected";
        wrappedAction.EndInvoke(result);
        return reply;
    }
    else
    {
        threadToKill.Abort();
        reply = "Error";
        return reply;            
    }      
}

然后我用类似的东西来称呼它:

string replyfromreader = CallWithTimeout(connectToHardware, 20000);

connectToHardware只是一个班轮,所以不需要张贴。

4

2 回答 2

1

就.NET 状态而言,这没问题。您不会调用 EndInvoke(),它会在 10 分钟内泄漏资源,这是远程对象的默认生命周期。

在这种情况下,调用 Thread.Abort() 成功的机会非常小。托管线程需要处于警报等待状态才能中止,它永远不会是当线程深埋在最终等待某些设备驱动程序调用完成的本机代码中时。

让 CLR 处于不断尝试中止线程并且从未成功的状态并不是特别令人愉快,这不是我故意尝试过的事情,因此不知道副作用是什么。但是,这确实意味着您的代码将阻塞 Abort() 方法调用,因此您仍然没有解决问题。因此,最好的办法是不要中止线程,而只是放弃它。设置一个标记设备死机的标志,这样您就不会再尝试这样做了。

如果您想继续运行您的程序,即使设备没有处于可用状态,并且您想提供一种从问题中恢复的方法,那么您将需要一种完全不同的方法。您需要将设备相关代码放在单独的进程中。然后你可以在设备无响应时使用 Kill(),依靠 Windows 来清理弹片。最好使用命名管道或套接字等低级机制与该进程进行互操作,这样您就可以很容易地从断开连接中恢复。

于 2012-09-07T11:10:56.537 回答
0

避免Thread.Abort总是一个好主意。在您没有创建的线程上避免它甚至更好。

假设如果硬件不工作,并且您想要超时,那么是否connectToHardware让其自行超时并且不需要错误/异常详细信息并不重要,那么您可以使用任务并行库(TPL)System.Threading.Tasks.Task::

// True => worked, False => timeout
public static bool CallWithTimeout(Action method, TimeSpan timeout) {
  Exception e;
  Task worker = Task.Factory.StartNew(method)
                    .ContineueWith(t => {
                      // Ensure any exception is observed, is no-op if no exception.
                      // Using closure to help avoid this being optimised out.
                      e = t.Exception;
                    });
  return worker.Wait(timeout);
}

(如果传递的Action可以与传递的交互,CancellationToken这可以变得更清晰,允许底层方法在超时时快速失败。)

于 2012-09-07T10:51:23.300 回答