繁体   English   中英

在无限循环中等待Task.Delay

[英]Doing await Task.Delay in an infinite loop

我有下面的代码,它将执行Action operation ,如果其中发生异常,将重试它。

因为代码正在await Task.Delay(delay); while(true) ,我在犹豫这是否会导致任何内存泄漏? 喜欢创建无限threads吗?

这段代码可以正常工作,但是我只担心可能发生内存泄漏? 如果有人可以分享一些见解,我将不胜感激。

public class OperationWithBasicRetry
{
  public async Task StartOperationAsync(Action operation, TimeSpan delay, int retryCount)
  {
    int currentRetry = 0;

    while(true)
    {
      try
      {
        operation();

        // Success
        break;
      }
      catch (Exception ex)
      {
        if (++currentRetry > retryCount)
        {
          throw;
        }
      }

      await Task.Delay(delay);
    }
  }
}

这很安全。

这是一个async方法,因此编译器将其切碎并将其变成状态机。 作为非常粗略的近似来说明这一点,您可以认为编译后的代码看起来像这样:

private class State
{
    public int currentRetry;
    public Action operation;
    public TimeSpan delay;
    public int retryCount;
    public TaskCompletionSource<object> tcs;

    private void StartOperationAsyncImpl(object unused)
    {
        try
        {
            operation();
            tcs.SetResult(null);
            return;
        }
        catch (Exception ex)
        {
            if (++currentRetry > retryCount)
            {
                tcs.SetException(ex);
            }
        }

        // I'm ignoring the delay bit, because it has no affect on the point
        // I'm trying to make.
        ThreadPool.QueueUserWorkItem(StateOperationAsyncImpl);
    }
}

public Task StartOperationAsync(Action operation, TimeSpan delay, int retryCount)
{
    State state = new State();
    state.currentRetry = 0;
    state.operation = operation;
    state.delay = delay;
    state.retryCount = retryCount;
    state.tcs = new TaskCompletionSource<object>();

    ThreadPool.QueueUserWorkItem(state.StartOperationAsyncImpl);

    return state.tcs;
}

当然,实际的已编译代码看起来并不像这样( 看起来像这样 ),但这说明了我的观点。

这里没有递归。 甚至没有无限循环。 您有一个方法,该方法在被调用时会尝试执行您的操作。 如果失败,则将其排队到ThreadPool上并返回。 ThreadPool.QueueUserWorkItem调用将立即返回,并且不会等到工作完成。

ThreadPool.QueueUserWorkItem也不创建新线程-它将要由预先存在的线程池执行的工作排队。

(在有人发表评论之前-我知道实际的编译后的代码不会直接使用ThreadPool.QueueUserWorkItem ,但可能会使用默认的TaskScheduler,它会在内部调用ThreadPool.UnsafeQueueUserWorkItem ,因此是一个很好的近似值)。

我认为不会,因为一旦满足retryCount条件,它要么通过break要么通过throw退出循环。 取决于您的retryCount ,这将导致内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM