用Task.Delay替换Thread.Sleep

时间:2019-07-02 01:06:23

标签: c# asynchronous async-await task

我正在重构使用Thread.Sleep的代码,该代码具有越来越长的时间限制,以便在出现错误时重试SQL查询。 Thread.Sleep用于阻塞的常见替代方法似乎是await Task.Delay,这需要将方法更改为async。该方法现在看起来像这样(为简便起见,删除了其他错误检查):

    private static async Task<int> PrepareForRetry( int retryCount, SqlCommand command, int timeout )
    {
        ++retryCount;
        if (retryCount < ConnectionRetryCount)
        {
            int SleepTime = _connectionRetryBackoffTimes[retryCount - 1] + (_connectionRetryRandomBackoff.Next() % 500);
            //Thread.Sleep(SleepTime);
            await Task.Delay(SleepTime);
        }
        return retryCount;
    }

我遇到的问题是async要求调用方法为async,依此类推。尽管最终可以重构为完全异步,但这远远超出了当前的重构范围。

我遇到的问题是如何从同步代码中调用方法并获取结果。使用

retryCount = PrepareForRetry(retryCount, command, timeout).Result;

创建死锁,因为UI线程正在调用该方法。我已经看到可以通过将Task.Delay更改为

来解决此问题
await Task.Delay(SleepTime).ConfigureAwait(false);

但是我不完全了解它的作用。我也尝试过使用

调用该方法
retryCount = Task.Run(async () => { await PrepareForRetry(retryCount, command, timeout).Result; });

但是它有错误“'int'不包含'GetAwaiter'的定义”,并且我无法找出如何继续获取结果的方法。使用Task.Delay是创建延迟的正确方法(计时器不允许增加等待时间),如果是这样,我应该如何调用该方法以获取返回值?

1 个答案:

答案 0 :(得分:3)

对于延迟,应该使用与实际操作相同的样式。如果您的SqlCommand是异步执行的,请使用Task.Delay进行延迟。如果您的SqlCommand是同步执行的,请使用Thread.Sleep进行延迟。

听起来您仍然需要SqlCommand同步执行(至少现在是这样),所以您应该使用Thread.Sleep。最终,您可以(同时)使它们都异步,但是听起来好像又要工作了一天。

Task.Delay在某种程度上是Thread.Sleep替换,这是不是。只是Task.DelayThread.Sleep的异步等效