Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建循环到true或timeout的等待任务_C#_Async Await - Fatal编程技术网

C# 创建循环到true或timeout的等待任务

C# 创建循环到true或timeout的等待任务,c#,async-await,C#,Async Await,我试图使用下面的函数不返回真/假,除非布尔函数arg返回真或超时过期。在当前状态下,如果布尔函数arg返回false,它将立即返回false,而不是循环并重试X毫秒 public delegate bool BooleanFunction (); public static async Task<bool> Wait(uint Milliseconds, BooleanFunction Function) { var StartTime = Env

我试图使用下面的函数不返回真/假,除非布尔函数arg返回真或超时过期。在当前状态下,如果布尔函数arg返回false,它将立即返回false,而不是循环并重试X毫秒

 public delegate bool BooleanFunction ();

    public static async Task<bool> Wait(uint Milliseconds, BooleanFunction Function)
    {
        var StartTime = Environment.TickCount;

        do
        {
            if (Function())
            {
                return true;
            }

            Thread.Yield();
        }
        while (Environment.TickCount < StartTime + Milliseconds);

        return false;
    }
公共委托布尔布尔函数();
公共静态异步任务等待(uint毫秒,布尔函数)
{
var StartTime=Environment.TickCount;
做
{
if(函数())
{
返回true;
}
螺纹屈服强度();
}
while(Environment.TickCount
您需要使用
等待任务。收益
而不是
线程。收益

    if (Function())
    {
        return true;
    }

    await Task.Yield();
如果您还希望处理将异步委托传递到
Wait
,请保留现有版本并添加以下重载:

public static async Task<bool> Wait(uint Milliseconds, Func<Task<bool>> Function)
{
    var StartTime = Environment.TickCount;

    do
    {
        if (await Function())
        {
            return true;
        }

        Thread.Yield();
    }
    while (Environment.TickCount < StartTime + Milliseconds);

    return false;
}

Microsoft提出了另一种实现方法,即使用cancellationTokenSource和cancellationToken

StackOverflow还有一些与此相关的主题:

转化为您的问题,调用方不会传递委托函数,而是传递System.Threading.CancellationToken对象。Wait函数不调用委托,而是定期检查CancellationToken对象是否请求取消

这个方法和你的非常相似,只是它是一个更标准的模式。真正的好处是,您可以在一次调用中取消所有使用同一来源令牌的任务。此外,它还有一个内置的超时功能

另一个优点是,取消的原因在函数外部决定,可以是超时,也可以是因为BooleanFunction返回true,甚至可能是因为程序停止等。即使在将来的版本中引入了新的停止等待的原因,您的等待函数也不必更改。它所做的只是做好工作,并定期检查是否需要取消

示例代码:

你的等待函数没有做很多事情,只是等待。我猜你简化了这个,因为如果这就是它真正需要做的,我猜你使用了System.Timer。让我们假设你必须做点什么

我有一个有两个按钮的表单:buttonStartWait和buttonCancelWait。按下按钮时,buttonStartWait将启动等待,而buttonCancelWait将取消等待

如果我们使用了您的方法,buttonCancelWait将使委托返回true

代码如下所示(我还将Ticks的用法改为TimeSpan,以便于阅读)

private CancellationTokenSource-tokenSource=null;
私有异步无效OnButtonStartWait_已单击(对象发送方,…)
{
this.buttonStartWait.Enabled=false;
TimeSpan waitTime=GetWaitTime();
this.tokenSource=新的tokenSource(waitTime);
//这确保在等待时间后取消请求
Wait this.Wait(this.TokenSource.Token);
this.buttonstartWait.Enabled=true;
}
专用异步任务等待(CancellationToken令牌)
{
而(!token.IsCancellationRequested)
{//做你的职责应该做的事情。
DoSomethingShort();
//如果此函数需要一些时间,请将令牌传递给它
//并让it部门定期检查是否有取消申请
DoSomethingLonger(代币);
或考虑启动定期检查的任务。
//如果要求取消
等待任务。运行(()=>DoSomethingLonger(令牌),令牌);
}
return token.IsCancellationRequested;
}
//一个Wait函数,除了Wait之外什么都不做
//直到要求取消为止。
专用异步任务等待(CancellationToken令牌)
{
而(!token.IsCancellationRequested)
{//请稍等
等待任务。等待(TimeSpan.FromSeconds(0.1),令牌;
}
return token.IsCancellationRequested;
}
私有异步无效OnButtonCancelWait_已单击(对象发送方,…)
{
if(this.TokenSource!=null)
{
this.TokenSource.Cancel();
}
}

这在Linqpad中工作,您如何测试它?谢谢ned,我已经做了一些调整,但是我无法正确调用它。错误:code:edit:updated code这是因为您的
Wait
函数只处理同步委托和
Test()
async
,请参阅我的更新答案以处理
async
问题。
   var result = await Wait(10000, async () => await Test());     
private CancellationTokenSource tokenSource = null;

private async void OnButtonStartWait_clicked(object sender, ...)
{
    this.buttonStartWait.Enabled = false;
    TimeSpan waitTime = GetWaitTime();        
    this.tokenSource = new tokenSource(waitTime);
    // this makes sure that after waitTime cancellation is requested
    await this.Wait(this.TokenSource.Token);
    this.buttonstartWait.Enabled = true;
}

private async Task<bool> Wait(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {   // do the thing your function is supposed to do.
        DoSomethingShort();

        // if this function takes some time, pass the token to it
        // and let it regularly check if cancellation is requested
        DoSomethingLonger(token);

        // or consider starting a Task which regularly checks
        // if cancellation is requested
        await Task.Run( () => DoSomethingLonger(token), token);
    }
    return token.IsCancellationRequested;
}

// a Wait function that really doesn't do anything but wait
// until cancellation is requested.
private async Task<bool> Wait(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {   // wait a short while
        await Task.Wait(TimeSpan.FromSeconds(0.1), token;
    }
    return token.IsCancellationRequested;
}

private async void OnButtonCancelWait_clicked(object sender, ...)
{
    if (this.TokenSource != null)
    {
        this.TokenSource.Cancel();
    }
}