Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.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# RuntimeMiddleware目标数组不够长错误_C#_Asp.net Core - Fatal编程技术网

C# RuntimeMiddleware目标数组不够长错误

C# RuntimeMiddleware目标数组不够长错误,c#,asp.net-core,C#,Asp.net Core,我在asp.net core 2.1中有一个写运行时中间件服务,它工作正常,但有时会出错 错误: 目标数组不够长。检查目标索引、长度和数组的下限 代码: 公共类运行时中间件服务 { 私有Func中间件; 私有IApplicationBuilder appBuilder; 内部无效使用(IApplicationBuilder应用程序) =>appBuilder=app.Use(next=>context=>middleware==null?next(上下文):middleware(next)(co

我在asp.net core 2.1中有一个写运行时中间件服务,它工作正常,但有时会出错

错误:

目标数组不够长。检查目标索引、长度和数组的下限

代码:

公共类运行时中间件服务
{
私有Func中间件;
私有IApplicationBuilder appBuilder;
内部无效使用(IApplicationBuilder应用程序)
=>appBuilder=app.Use(next=>context=>middleware==null?next(上下文):middleware(next)(context));
公共无效配置(操作)
{
var app=appBuilder.New();
行动(app);
middleware=next=>app.Use(=>next.Build();//行获取错误
}
}

我也使用了来自

堆栈跟踪 需要注意的是:

foreach (var component in _components.Reverse())
Reverse
调用
ReverseIterator

集合是通过引用传递的。似乎在获取集合计数和创建相同大小的新数组之间的某个地方,集合的大小增加超过
TElement
数组的大小,导致错误“目标数组不够长。请检查目标索引、长度和数组的下限。(参数'destinationArray')。“这将提示线程安全问题,并解释间歇性错误

下一个问题是,线程安全问题的根源在哪里

这对我个人来说还是一个谜。
RuntimeMiddlewareService
在我的应用程序中是在启动时创建的一个单例。它的
Configure
函数肯定会被调用,但调用频率不够(据我所知)因此,
\u中间件
Func
可能在其他地方被调用。也就是说,在调用Use和Build时添加一个锁对象解决了这个问题,可能是因为线程1调用了
Build
,线程2刚刚调用了
Use
(这会将新项目添加到
集合

公共类RuntimeMiddlewareService:IRuntimeMiddlewareService
{
私有静态只读对象_middlewareLock=新对象();
私有函数中间件;
私有IApplicationBuilder\u appBuilder;
公共作废使用(IApplicationBuilder应用程序)
=>\u appBuilder=app.Use(next=>context=>\u middleware==null?next(context):\u middleware(next)(context));
公共无效配置(操作)
{
var app=_appBuilder.New();
行动(app);
_中间件=下一步=>
{
锁(_middlewareLock)
{
返回app.Use(=>next.Build();
}
};
}
}

我也使用了来自

堆栈跟踪 需要注意的是:

foreach (var component in _components.Reverse())
Reverse
调用
ReverseIterator

集合是通过引用传递的。似乎在获取集合的计数和创建相同大小的新数组之间的某个地方,集合的大小增加超过
TElement
数组的大小,从而导致错误“目标数组不够长。请检查目标索引、长度和数组的下限。(参数'destinationArray')。”这将提示线程安全问题并解释间歇性错误

下一个问题是,线程安全问题的根源在哪里

这对我个人来说还是一个谜。
RuntimeMiddlewareService
在我的应用程序中是在启动时创建的一个单例。它的
Configure
函数肯定会被调用,但调用频率不够(据我所知)因此,
\u中间件
Func
可能在其他地方被调用。也就是说,在调用Use和Build时添加一个锁对象解决了这个问题,可能是因为线程1调用了
Build
,线程2刚刚调用了
Use
(这会将新项目添加到
集合

公共类RuntimeMiddlewareService:IRuntimeMiddlewareService
{
私有静态只读对象_middlewareLock=新对象();
私有函数中间件;
私有IApplicationBuilder\u appBuilder;
公共作废使用(IApplicationBuilder应用程序)
=>\u appBuilder=app.Use(next=>context=>\u middleware==null?next(context):\u middleware(next)(context));
公共无效配置(操作)
{
var app=_appBuilder.New();
行动(app);
_中间件=下一步=>
{
锁(_middlewareLock)
{
返回app.Use(=>next.Build();
}
};
}
}

发生此错误时,您可以与我们共享堆栈跟踪。发生此错误时,您可以与我们共享堆栈跟踪。
private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();

public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
    _components.Add(middleware);
    return this;
}

public RequestDelegate Build()
{
    RequestDelegate app = context =>
    {
        // If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened.
        // This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware.
        var endpoint = context.GetEndpoint();
        var endpointRequestDelegate = endpoint?.RequestDelegate;
        if (endpointRequestDelegate != null)
        {
            var message =
                $"The request reached the end of the pipeline without executing the endpoint: '{endpoint.DisplayName}'. " +
                $"Please register the EndpointMiddleware using '{nameof(IApplicationBuilder)}.UseEndpoints(...)' if using " +
                $"routing.";
            throw new InvalidOperationException(message);
        }

        context.Response.StatusCode = 404;
        return Task.CompletedTask;
    };

    foreach (var component in _components.Reverse())
    {
        app = component(app);
    }

    return app;
}
foreach (var component in _components.Reverse())
public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    return ReverseIterator<TSource>(source);
}

static IEnumerable<TSource> ReverseIterator<TSource>(IEnumerable<TSource> source) {
    Buffer<TSource> buffer = new Buffer<TSource>(source);
    for (int i = buffer.count - 1; i >= 0; i--) yield return buffer.items[i];
}
struct Buffer<TElement>
{
    internal TElement[] items;
    internal int count;

    internal Buffer(IEnumerable<TElement> source) {
        TElement[] items = null;
        int count = 0;
        ICollection<TElement> collection = source as ICollection<TElement>;
        if (collection != null) {
            count = collection.Count;
            if (count > 0) {
                items = new TElement[count];
                collection.CopyTo(items, 0);
            }
        }
        else {
            foreach (TElement item in source) {
                if (items == null) {
                    items = new TElement[4];
                }
                else if (items.Length == count) {
                    TElement[] newItems = new TElement[checked(count * 2)];
                    Array.Copy(items, 0, newItems, 0, count);
                    items = newItems;
                }
                items[count] = item;
                count++;
            }
        }
        this.items = items;
        this.count = count;
    }

    internal TElement[] ToArray() {
        if (count == 0) return new TElement[0];
        if (items.Length == count) return items;
        TElement[] result = new TElement[count];
        Array.Copy(items, 0, result, 0, count);
        return result;
    }
}
if (collection != null) {
    count = collection.Count;
    if (count > 0) {
        items = new TElement[count];
        collection.CopyTo(items, 0);
    }
}
public class RuntimeMiddlewareService : IRuntimeMiddlewareService
{
    private static readonly object _middlewareLock = new object();
    private Func<RequestDelegate, RequestDelegate> _middleware;

    private IApplicationBuilder _appBuilder;

    public void Use(IApplicationBuilder app)
    => _appBuilder = app.Use(next => context => _middleware == null ? next(context) : _middleware(next)(context));

    public void Configure(Action<IApplicationBuilder> action)
    {
        var app = _appBuilder.New();
        action(app);
        _middleware = next =>
        {
            lock (_middlewareLock)
            {
                return app.Use(_ => next).Build();
            }
        };
    }
}