此扩展方法安全吗?

我很难把头放在扩展方法上。它们是静态类中的静态方法。它们如何在内部初始化?例如,我写了下面的扩展方法。它是线程安全的吗?

public static async Task TimeoutAfter(this Task task, TimeSpan timeSpan)
{
    var cts = new CancellationTokenSource();
    try
    {
        if (task.IsCompleted || timeSpan == Timeout.InfiniteTimeSpan)
            return;
        if (timeSpan == TimeSpan.Zero)
            throw new TimeoutException();
        if (task == await Task.WhenAny(task, Task.Delay(timeSpan, cts.Token)))
        {
            cts.Cancel();
            await task;
        }
        else
        {
            throw new TimeoutException();
        }
    }
    finally
    {
        cts.Dispose();
    }
}
斯科特·张伯伦

所有扩展方法要做的就是转

var result = myTask.TimeoutAfter(TimeSpan.FromSecconds(5));

进入

var result = ExtensionMethodClass.TimeoutAfter(myTask, TimeSpan.FromSecconds(5));

没别的。因此,无论函数是否是扩展方法,都根本不会影响其行为,这只是说服程序员不必从我上面的示例中键入长版本。

至于您的代码是否是线程安全的,首先您需要了解“线程安全”的含义。我强烈建议您阅读埃里克·利珀特(Eric Lippert)的文章“什么叫做“线程安全”? ”,它将极大地帮助您了解线程安全的含义。

您的代码不会从其作用域访问或更改任何外部变量,因此该函数本身是线程安全的,但这并不意味着它不能以“线程不安全”的方式使用。幸运的是,您TaskTimeSpan我俩都很幸运,并且在它们的所有方法和属性上保证了线程安全,因此您不太可能遇到任何线程安全问题。


不管怎么说,您确实有一个带有竞争条件的错误。如果task.IsCompleted返回true并task引发异常,则永远不会收到该异常的通知。另外,timeSpan == Timeout.InfiniteTimeSpan即使传入的任务仍在运行,函数仍将立即返回完成的任务。await即使您不打算进行超时,也需要执行任务。另外,您的try / finally可以简化为一个using语句

public static async Task TimeoutAfter(this Task task, TimeSpan timeSpan)
{
    using(var cts = new CancellationTokenSource())
    {
        if (task.IsCompleted || timeSpan == Timeout.InfiniteTimeSpan)
        {
            await task;
            return;
        }
        if (timeSpan == TimeSpan.Zero)
            throw new TimeoutException();
        if (task == await Task.WhenAny(task, Task.Delay(timeSpan, cts.Token)))
        {
            cts.Cancel();
            await task;
        }
        else
        {
            throw new TimeoutException();
        }
    }
}

最后,如果您还没有做过,那么您将需要制作一个版本,Task<T>以防万一您要使返回结果的任务超时。

public static async Task<T> TimeoutAfter<T>(this Task<T> task, TimeSpan timeSpan)
{
    using(var cts = new CancellationTokenSource())
    {
        if (task.IsCompleted || timeSpan == Timeout.InfiniteTimeSpan)
        {
            return await task
        }
        if (timeSpan == TimeSpan.Zero)
            throw new TimeoutException();
        if (task == await Task.WhenAny(task, Task.Delay(timeSpan, cts.Token)))
        {
            cts.Cancel();
            return await task;
        }
        else
        {
            throw new TimeoutException();
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C#此方法线程安全吗?

来自分类Dev

此MessageDigest包装器线程安全吗?

来自分类Dev

通过并发访问此线程安全吗?

来自分类Dev

libgdx中的此方案线程安全吗?

来自分类Dev

此汇编函数调用安全/完整吗?

来自分类Dev

SQL注入-此查询安全吗?

来自分类Dev

Spring:此成员变量是线程安全的吗?

来自分类Dev

此代码不是线程安全的吗?

来自分类Dev

此无锁设计线程安全吗?

来自分类Dev

从/以root身份运行此命令安全吗?

来自分类Dev

此代码字节序安全吗?

来自分类Dev

此汇编函数调用安全/完整吗?

来自分类Dev

移动此EFI分区安全吗?

来自分类Dev

此副本分配操作安全吗?

来自分类Dev

此移动/调整大小操作安全吗?

来自分类Dev

此代码是线程安全的吗?修改HTTP Servlet请求的静态方法

来自分类Dev

此Auth0身份验证方法对CLI安全吗?

来自分类Dev

有什么方法可以使此代码更小/更快?...运行安全吗?

来自分类Dev

我的方法安全吗?

来自分类Dev

静态方法是线程安全的吗?

来自分类Dev

此无括号的C预处理程序定义安全吗?

来自分类Dev

此更新选择组合查询线程安全吗?

来自分类Dev

此代码可安全用于SQL Injection吗?

来自分类Dev

我可以禁用此Windows(XP)安全警告吗?

来自分类Dev

应用程序空闲-此线程安全吗?

来自分类Dev

继承是解决此问题的正确方法吗?

来自分类Dev

此hashCode方法会溢出吗?

来自分类Dev

类方法线程安全吗?

来自分类Dev

会话集成,这种方法安全吗?