加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 在.Net 4.0中使用差的mans async / await构造实现异步超时

发布时间:2020-12-15 08:22:54 所属栏目:百科 来源:网络整理
导读:动机 C#5.0异步/等待构造非常棒,但遗憾的是,微软只展示了.NET 4.5和VS 2012的候选版本,这些技术将在我们的项目中得到广泛采用需要一些时间. 在Stephen Toub的Asynchronous methods,C# iterators,and Tasks中,我找到了一个可以很好地用于.NET 4.0的替代品.还
动机

C#5.0异步/等待构造非常棒,但遗憾的是,微软只展示了.NET 4.5和VS 2012的候选版本,这些技术将在我们的项目中得到广泛采用需要一些时间.

在Stephen Toub的Asynchronous methods,C# iterators,and Tasks中,我找到了一个可以很好地用于.NET 4.0的替代品.还有十几个其他实现甚至可以在.NET 2.0中使用该方法,尽管它们看起来很少过时且功能较少.

所以现在我的.NET 4.0代码看起来像(注释部分显示它是如何在.NET 4.5中完成的):

//private async Task ProcessMessageAsync()
private IEnumerable<Task> ProcessMessageAsync()
{
    //var udpReceiveResult = await udpClient.ReceiveAsync();

    var task = Task<UdpAsyncReceiveResult>
               .Factory
               .FromAsync(udpClient.BeginReceive,udpClient.EndReceive,null);

    yield return task;

    var udpReceiveResult = task.Result;

    //... blah blah blah

    if (message is BootstrapRequest)
    {
        var typedMessage = ((BootstrapRequest)(message));

        // !!! .NET 4.0 has no overload for CancellationTokenSource that 
        // !!! takes timeout parameter :(
        var cts 
          = new CancellationTokenSource(BootstrapResponseTimeout); // Error here

        //... blah blah blah

        // Say(messageIPEndPoint,responseMessage,cts.Token);

        Task.Factory.Iterate(Say(messageIPEndPoint,cts.Token));
    }
}

看起来有点难看虽然它能完成这项工作

这个问题

在.NET 4.5中使用CancellationTokenSource时,有一个构造函数将时间跨度作为超时参数,因此生成的CancellationTokenSource在指定的时间段内取消.
.Net 4.0无法超时,那么在.Net 4.0中这样做的正确方法是什么?

解决方法

这真的与async / await有关吗?看起来你只需要一种取消令牌的方法,独立于异步/等待,对吗?在这种情况下,您可以简单地创建一个在超时后调用取消的Timer吗?
new Timer(state => cts.Cancel(),null,BootstrapResponseTimeout,Timeout.Infinite);

编辑

我上面的初步回答是基本思路,但是在Is CancellationTokenSource.CancelAfter() leaky?中可以找到更强大的解决方案(实际上是你正在寻求的构造函数的.Net 4.5实现).这是一个可用于根据该代码创建超时令牌的函数.

public static CancellationTokenSource CreateTimeoutToken(int dueTime) {
    if (dueTime < -1) {
        throw new ArgumentOutOfRangeException("dueTime");
    }
    var source = new CancellationTokenSource();
    var timer = new Timer(self => {
        ((Timer)self).Dispose();
        try {
            source.Cancel();
        } catch (ObjectDisposedException) {}
    });
    timer.Change(dueTime,-1);
    return source;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读