【问题标题】:How to set timeout for a line of c# code [duplicate]如何为一行c#代码设置超时[重复]
【发布时间】:2012-11-10 21:47:03
【问题描述】:

可能重复:
Set timeout to an operation

如何在 c# 中为一行代码设置超时。 例如 RunThisLine(SomeMethod(Some Input), TimeSpan.FromSeconds(10)) 运行 SomeMethod 10 秒超时。 提前致谢。

【问题讨论】:

  • 那“行”代码是否协作,即它是否支持取消?
  • 不行,线路处理必须限制在指定时间。

标签: c# timeout


【解决方案1】:

您可以使用Task Parallel Library。更准确地说,你可以使用Task.Wait(TimeSpan)

using System.Threading.Tasks;

var task = Task.Run(() => SomeMethod(input));
if (task.Wait(TimeSpan.FromSeconds(10)))
    return task.Result;
else
    throw new Exception("Timed out");

【讨论】:

  • 太棒了。 SomeMethod 的结果将在 task.Result 变量中。谢谢。
  • 如果您只需要超时,则不必使用CancellationToken,和/或您的方法在取消时不处理令牌。等待有一个没有token 的过载,它工作得很好。
  • 这是一个很好的解决方案,但这不是停止功能。只通知超时。
  • sn-p 仍然会等待 10s,即使 SomeMethod 在 2s 内响应。
  • @ValerianPereira:根据MSDN(见备注),它不应该阻塞直到a)任务成功完成,b)任务抛出异常或 c) 任务超时。
【解决方案2】:

您可以使用 IAsyncResult 和 Action 类/接口来实现这一点。

public void TimeoutExample()
{
    IAsyncResult result;
    Action action = () =>
    {
        // Your code here
    };

    result = action.BeginInvoke(null, null);

    if (result.AsyncWaitHandle.WaitOne(10000))
         Console.WriteLine("Method successful.");
    else
         Console.WriteLine("Method timed out.");
}

【讨论】:

  • 使用非常简单!!但这是否也会杀死其他任务? (在超时的情况下)
  • 其他任务 = 动作*
【解决方案3】:

我使用这样的东西(你应该添加代码来处理各种失败):

    var response = RunTaskWithTimeout<ReturnType>(
        (Func<ReturnType>)delegate { return SomeMethod(someInput); }, 30);


    /// <summary>
    /// Generic method to run a task on a background thread with a specific timeout, if the task fails,
    /// notifies a user
    /// </summary>
    /// <typeparam name="T">Return type of function</typeparam>
    /// <param name="TaskAction">Function delegate for task to perform</param>
    /// <param name="TimeoutSeconds">Time to allow before task times out</param>
    /// <returns></returns>
    private T RunTaskWithTimeout<T>(Func<T> TaskAction, int TimeoutSeconds)
    {
        Task<T> backgroundTask;

        try
        {
            backgroundTask = Task.Factory.StartNew(TaskAction);
            backgroundTask.Wait(new TimeSpan(0, 0, TimeoutSeconds));
        }
        catch (AggregateException ex)
        {
            // task failed
            var failMessage = ex.Flatten().InnerException.Message);
            return default(T);
        }
        catch (Exception ex)
        {
            // task failed
            var failMessage = ex.Message;
            return default(T);
        }

        if (!backgroundTask.IsCompleted)
        {
            // task timed out
            return default(T);
        }

        // task succeeded
        return backgroundTask.Result;
    }

【讨论】:

  • 请注意:这不会在超时后取消操作。我并不是说它应该这样做——我之所以提到它是因为我认为这是一个重要的细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 2021-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多