Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.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# Task.wait可等待项的任何功能_C#_Asynchronous - Fatal编程技术网

C# Task.wait可等待项的任何功能

C# Task.wait可等待项的任何功能,c#,asynchronous,C#,Asynchronous,由于在异步函数中等待了0.25秒,我当前正处于竞争状态。取消令牌在循环中检查,但由于等待而延迟 我正在使用一个提供“wait.Until”功能的库,它允许等待布尔值。因此,我考虑等待0.25秒,或者token.isCancelled为true 我确信,将它们外包到单独的任务中,然后使用Task.waitAny()会起作用,但这似乎有点过头了。有没有更优雅的方式来等待多个等待者 while (!Completed) { Completed = AdjustPath(); awai

由于在异步函数中等待了0.25秒,我当前正处于竞争状态。取消令牌在循环中检查,但由于等待而延迟

我正在使用一个提供“wait.Until”功能的库,它允许等待布尔值。因此,我考虑等待0.25秒,或者token.isCancelled为true

我确信,将它们外包到单独的任务中,然后使用Task.waitAny()会起作用,但这似乎有点过头了。有没有更优雅的方式来等待多个等待者

while (!Completed)
{
    Completed = AdjustPath();

    await Await.Seconds(PathingDelay);

    if (!loop) 
        return Completed;
    else if (token.IsCancellationRequested)
    {
        StopMove();

        return false;
    }
}
上面的问题是再次调用包含函数,在取消解决之前设置目标,停止对象并删除目标。虽然我可以等待任务完成,但这会增加方法运行的延迟,这并不理想。

使用,就像Dmitry在评论中已经提出的那样

while (!Completed)
{
    Completed = AdjustPath();

    try
    {
        await Task.Delay(PathingDelay, token);
    }
    catch(TaskCanceledException e){} // if delay was cancelled is checked in next lines

    if (!loop) 
        return Completed;
    else if (token.IsCancellationRequested)
    {
        StopMove();

        return false;
    }
}

使用
TaskCompletionSource
可以构建一个
任务
,当给定的
CancellationToken
请求取消时,该任务将完成

public static class Async
{
    private static readonly TaskCompletionSource<bool> _neverComplete = new TaskCompletionSource<bool>();

    public static Task CompleteOnCancellation( CancellationToken token )
    {
        if ( !token.CanBeCanceled )
            return _neverComplete.Task;
        if ( token.IsCancellationRequested )
            return Task.CompletedTask;

        var tcs = new TaskCompletionSource<bool>();

        token.Register( () => tcs.SetResult( true ) );

        return tcs.Task;
    }
}

看看Task.Delay,它接受一个可选的CancellationToken(针对这个特定问题)任务。Delay在被取消时不会返回控制并传递等待,因此不会执行必要的中断功能。据我所知,wait不能在try-catch语句中,但task.wait可以(尽管会阻塞线程)。我不确定这是否行得通,但我稍后会尝试一下。Wait可能从C#6开始就处于catch块中,并且可能始终处于try块中。根据文档,您确实是正确的。我不确定我在哪里看到它不能。可能相关:取消延迟似乎会返回整个函数,因为我相信它会引发异常。这也不理想,因为它排除了在取消时调用StopMove()。我的评估正确吗?虽然这看起来比其他解决方案更优雅,但我不确定它是否适用于此特定实例,因为似乎没有办法从令牌中删除已注册的代理,并且令牌只有在取消时才会续订。这似乎会导致将多个相同的委托分配给令牌,并运行过多的“StopMove()”调用。这不是功能上的问题,但似乎是不好的做法。然而,在任务链完成时更新令牌可能是可行的。这不会给我的大脑带来任何问题。
using var cts = new CancellationTokenSource( 100 );

var longWaitingTask = Task.Delay( 250 );
var cancellationTask = Async.CompleteOnCancellation( cts.Token );

var completedTask = await Task.WhenAny( longWaitingTask, cancellationTask );

if ( completedTask == longWaitingTask )
{
    Console.WriteLine( "Long Running Task completed." );
}
if ( completedTask == cancellationTask )
{
    Console.WriteLine( "Cancellation Task completed." );
}