如何创建可配置的Asynctimeout

时间:2015-03-16 13:28:58

标签: c# asp.net asp.net-mvc

我想为我的AsyncController设置一个可配置的超时值。我知道我们可以使用[AsyncTimeout(5000)]属性修饰方法,我们也可以将该值与const变量一起使用。我想使用静态变量,以便我可以使用更可配置的方式在编译后设置超时。

阅读此AsyncManager似乎有一个名为timeout的属性可以设置。

这是我尝试过的。

[HttpPost]
    public void DoWorkAsync(MyQuery query)
    {
        AsyncManager.Timeout = TestTimeout; //TestTimeout is a static int set to 120000
        AsyncManager.OutstandingOperations.Increment();
        (do work)...
    }

似乎没有使用AsyncManager.Timeout值,而是在默认的45秒后抛出TimeoutException。

有没有办法在编译时设置此超时值?

2 个答案:

答案 0 :(得分:4)

您可以像这样

创建从AsyncTimeoutAttribute派生的类
public class CustomAsyncTimeoutAttribute : AsyncTimeoutAttribute
{
    public CustomAsyncTimeoutAttribute() : base(Params.TimeOut)
    {}       
}

其中Params.Timeout包含您的静态超时变量。

或者您可以尝试此操作(只需复制/粘贴基本AsyncTimeout功能):

public class CustomAsyncTimeoutAttribute : AsyncTimeoutAttribute
{
    public CustomAsyncTimeoutAttribute() : base(0)
    {}

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext == null)
            throw new ArgumentNullException("filterContext");
        var managerContainer = filterContext.Controller as IAsyncManagerContainer;
        if (managerContainer == null)
            throw new InvalidOperationException("The operation has timed out.");
        managerContainer.AsyncManager.Timeout = //There you can get your timeout parameter from resourse (i.e. config file, database, etc);
        base.OnActionExecuting(filterContext);
    }
}

此外,您应该使用async关键字标记您的操作方法,您的方法应该返回TaskTask<T>,方法的最后一个参数应为CancellationToken,否则AsyncTimeout无效。

例如:

[CustomAsyncTimeoutAttribute]
public async Task PerformAction(/*Some parameters*/, CancellationToken token)

答案 1 :(得分:0)

您真的不需要从AsyncTimeoutAttribute继承。只需创建自己的CustomAsyncTimeoutAttribute并直接从ActionFilterAttribute继承它。否则base.OnActionExecuting(filterContext)将覆盖你的,你肯定会有TimeoutException,因为你在基础构造函数中发送0。

以下是您实现目标的方法。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAsyncTimeoutAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException(nameof(filterContext));
        }

        var managerContainer = filterContext.Controller as IAsyncManagerContainer;
        if (managerContainer == null)
        {
            throw new InvalidOperationException("CustomAsyncTimeout Action Filter failed");
        }

        var duration = GetYouDurationAsYouWish();
        if (duration < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(duration));
        }

        managerContainer.AsyncManager.Timeout = duration;
        base.OnActionExecuting(filterContext);
    }
}