【问题标题】:C# How to wait X seconds for a task to complete [closed]C#如何等待X秒完成任务[关闭]
【发布时间】:2018-02-18 21:57:50
【问题描述】:

我想在不阻塞线程的情况下等待任务完成指定的时间量,并根据任务是否完成执行某些工作。
例如等待特定时间的 HTTP 请求。

【问题讨论】:

  • 您是否要继续检查“MyCondition”直到其为真但在 x 秒后“超时”?因此,如果 MyCondition 为真,您将立即返回,但如果它从未评估为真,那么您将等待 x 秒以等待它可能发生变化,如果不返回?还是要一直等待 x 秒?
  • @Dave 第一个
  • 你得到古怪的答案是因为人们不明白你在做什么。 “在sec 之后退货”和“在sec 期间”有什么区别? MyCondition 是什么? describe your goal. 而不是向我们展示你想要做什么
  • @DourHighArch 我很抱歉。这显然是我的缺陷,因为我说英语太糟糕了。我想做的最好的例子是一个在开始时检查互联网连接的程序。该程序 2 秒检查互联网连接,如果有连接程序立即进入下一步,如果 2 秒后没有连接,用户可以单击按钮重试连接到互联网。这就是我想要构建的。

标签: c# task delay


【解决方案1】:

计算你的结束时间,然后等到那个时间过去。

public void TrySomething(int sec)
{
    DateTime endTime = DateTime.Now.AddSeconds(sec);
    while (DateTime.Now < endTime)
    {
         // do useful stuff
    }
}

【讨论】:

  • for sec 第二个应用程序没有响应。我希望应用程序在循环期间响应。
  • 不要使用DateTime - 使用Stopwatch 处理这种事情。
【解决方案2】:

一般而言,您可以使用 CancellationTokenSource,如果该期限已过,它将将令牌 IsCancellationRequested 属性设置为 true。因此,您的代码将是。

public bool TrySomething(int sec)
{
    var ct = new CancellationTokenSource(TimeSpan.FromSeconds(sec)).Token;
    var valueToReturne=false;
    while (!ct.IsCancellationRequested)
    {
        if (!MyCondition)
                    continue;
        else
                    valueToReturne = true;
    }
    return valueToReturne;
}

但是,与其他解决方案类似,这是一个繁忙的循环,意味着阻塞您的主线程。

如果你想让你停止编程而不响应,你需要让你的方法异步,例如通过在 Task.Run 中包装 TrySomething,例如

var ct = new CancellationTokenSource(TimeSpan.FromSeconds(sec)).Token;
await Task.Run(() => TrySomething(ct), ct);

public bool TrySomething(CancellationToken ct)
{
    var valueToReturne=false;
    while (!ct.IsCancellationRequested)
    {
        if (!MyCondition)
                    continue;
        else
                    valueToReturne = true;
    }
    return valueToReturne;
}

但是,这应该只适用于 CPU 密集型工作。但是你说你想检查你的互联网连接,这是 IO 绑定的工作。您仍然可以使用 Task.Run,​​但在这种情况下,这是非常不受欢迎的。最佳解决方案是使用适当的异步方法进行 Internet 连接检查,例如如果您使用 Ping.Send 检查互联网连接,则应使用 Ping.SendAsync 等。

在这种情况下,您的代码将是:

var ct = new CancellationTokenSource(TimeSpan.FromSeconds(sec)).Token;
await TrySomething(ct);

public async Task<bool> TrySomethingAsync(CancellationToken ct)
{
    var valueToReturne=false;
    while (!ct.IsCancellationRequested)
    {
        if (!await MyConditionAsync(ct))
                    continue;
        else
                    valueToReturne = true;
    }
    return valueToReturne;
}

【讨论】:

    【解决方案3】:

    Stopwatch 是这里的路:

    public void TrySomething(int sec)
    {
        var sw = Stopwatch.StartNew();
        while (sw.Elapsed.TotalSeconds < (double)sec)
        {
             // do useful stuff
        }
    }
    

    甚至:

    public void TrySomething(int sec)
    {
        var sw = Stopwatch.StartNew();
        while (true)
        {
            var result = ...
            // do useful stuff
            if (sw.Elapsed.TotalSeconds >= (double)sec)
            {
                return result;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      相关资源
      最近更新 更多