我可以编写一个通用方法来调用其他超时方法吗?

发布于 2024-08-05 20:19:38 字数 638 浏览 6 评论 0原文

我有一个很多人都熟悉的问题:我正在进行一个调用(具体来说是 Forest.GetCurrentForest()),在某些情况下,该调用将无法工作并引发异常。问题不大,抓住它并适当处理即可。然而,当调用失败时,速度非常慢;完全完成需要 30 秒。

我寻找一种调用该方法的方法,但设置了一个超时,以便我们可以在更短的时间后停止。我发现了一个有趣的建议 这里,但如果我能解决的话,我想要一个更通用的解决方案。该解决方案还需要额外的大量工作才能获得超时。我希望这会像“

CallMethodWithTimeout(Delegate method, int timeout)

但我不确定这样的事情是否会起作用”一样简单。对于做类似的事情有什么建议,或者在 C# 中这是不可能的吗?我们还被困在使用.NET 2.0 上。

除此之外,我将就如何避免 GetCurrentForest() 调用花费 30 秒才能发现它没有发生进行评论。虽然我想知道通用方法调用者方法的可行性。

I have a problem that is surely familiar to many: I'm making a call (to be specific it is Forest.GetCurrentForest()) which, in some circumstances, will fail to work and throw an exception. Not a huge problem, just catch it and deal appropriately. However the call, when it fails, is very slow; it takes 30 seconds to fully finish.

I went looking for a way to call that method but set-up a timeout so we can stop after a shorter time. I found an interesting suggestion here but I'd like a more general solution if I can work it out. That solution is also rather heavy on extras just to get a timeout. I hoped it would be as easy as, say

CallMethodWithTimeout(Delegate method, int timeout)

But I'm not sure something like that is going to work. Any suggestions on doing something like that, or is it just not possible in C# ? We're also stuck using .NET 2.0.

Barring that, I'll take comments on keeping the GetCurrentForest() call from taking 30 seconds to figure out that it isn't happening. Though I would like to know about the feasibility of that general method caller method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

み格子的夏天 2024-08-12 20:19:38

我想了想,想出了以下方法(本质上是迈克尔在编码时编写的内容的实现):

private static bool TimedMethodCaller(Delegate dlgt, int timeout, 
    params object[] args)
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    Thread t = new Thread(new ThreadStart(delegate
        {
            dlgt.Method.Invoke(dlgt.Target, args);
            waitHandle.Set();
        }));
    t.Start();
    return waitHandle.WaitOne(timeout);
}

使用此方法,您可以发布您想要的任何委托和参数。它确实有一个缺点,即它不处理返回值(但这也可以通过某种方式实现)。

你可以这样调用它:

// parameter-less method call
bool success = TimedMethodCaller(new Action(ParamlessTestMethod), 100);

如果你想调用一个带有参数的方法,你将需要一个合适的委托:

// call with one parameter (using the Action<T> delegate of the framework
bool success = TimedMethodCaller(new Action<int>(TestMethod), 100, "text"); 

// call with several parameters using custom delegate that is defined like this:
// public delegate void SampleDelegate(string text, int numeric);
bool success = TimedMethodCaller(new SampleDelegate(TestMethod), 100, "text", 1);

I gave it a bit of thought and came up with the following method (which essentially is an implementation of what Michael wrote while I was coding it):

private static bool TimedMethodCaller(Delegate dlgt, int timeout, 
    params object[] args)
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    Thread t = new Thread(new ThreadStart(delegate
        {
            dlgt.Method.Invoke(dlgt.Target, args);
            waitHandle.Set();
        }));
    t.Start();
    return waitHandle.WaitOne(timeout);
}

Using this method you can post in whatever delegate and parameters you feel like. It does have the shortcoming that it doesn't handle return values (but that can probably be achieved as well in some way).

You can call it like so:

// parameter-less method call
bool success = TimedMethodCaller(new Action(ParamlessTestMethod), 100);

If you want to call a method that takes parameters you will need a fitting delegate:

// call with one parameter (using the Action<T> delegate of the framework
bool success = TimedMethodCaller(new Action<int>(TestMethod), 100, "text"); 

// call with several parameters using custom delegate that is defined like this:
// public delegate void SampleDelegate(string text, int numeric);
bool success = TimedMethodCaller(new SampleDelegate(TestMethod), 100, "text", 1);
半仙 2024-08-12 20:19:38

您不能直接将不可取消的操作设为可取消 (此链接描述了代码中异步异常的一些问题,但尚未对其进行强化。)

我见过的一种模式是将工作排队到另一个线程,但只等待有限的时间完成,在花费太长时间时有效地放弃请求。这并不能完全取消,但它可以帮助您的应用程序保持响应能力。

You can't directly make non-cancellable operations cancellable (this link describes some issues with asynchronous exceptions in code that hasn't been hardened for it.)

One pattern I've seen is to queue the work to another thread, but only wait for a limited time for it complete, effectively abandoning the request when it takes too long. This doesn't out-right cancel, but it can help keep your application responsive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文