簡體   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