简体   繁体   English

访问Collection时是否ArgumentOutOfRangeException,即使索引未超出范围?

[英]ArgumentOutOfRangeException when accessing a Collection, even though index is not out of range?

I have an application which processes images through a series of image filters in one thread, and displays the images in a UI on another thread. 我有一个应用程序,该应用程序通过一个线程中的一系列图像过滤器处理图像,并在另一个线程中的UI中显示图像。 The simplified image filter class looks like this: 简化的图像过滤器类如下所示:

// This class represents a filter operation on the GPU.
// Process() is repeatedly called by the filter processing thread.
class ShaderFilterBase : IFilter
{
    // This variable holds the result of the image operation.
    private ImageInfo resultImageInfo;

    // Indicates whether the image has been updated by a call to Render()
    bool hasChanged = true;

    public ICollection<ImageInfo> LastResults
    {
        get
        {
            ICollection<ImageInfo> results = new Collection<ImageInfo>();
            results.Add(GetEffectResult());
            return results;
        }
    }

    public ICollection<ImageInfo> Process(ICollection<ImageInfo> images)
    {
        // We only process the image if we have exactly one image.
        // If more than one image has to be processed by the GPU, this method
        // should be overridden in a derived class.
        if (images.Count == 1)
        {
            ImageInfo firstImage = images.First();

            // If the supplied image is already a shader resource on the GPU,
            // we don't need to upload the texture to the GPU again. We just
            // set the output texture of the supplied image to the input texture
            // of the current image.
            if (firstImage.IsShaderResource)
                SetResource(firstImage.ShaderResourceView);
            else
                UploadInputTexture(firstImage);

            Render();

            firstImage.ShaderResourceView = OutputShaderResourceView;
        }

        return images;
    }

    public virtual void Render()
    {
        Monitor.Enter(this);

        // Perform texture operations on the GPU            

        hasChanged = true;

        Monitor.Exit(this);
    }

    public ImageInfo GetEffectResult()
    {
        Monitor.Enter(this);

        if (hasChanged)
        {
            // Download image from GPU and store it in resultImageInfo

            hasChanged = false;
        }

        Monitor.Exit(this);

        return resultImageInfo;
    }
}

Furthermore, I have various derived classes which differ by the HLSL shader program to be executed on the GPU. 此外,我有各种派生类,这些派生类因要在GPU上执行的HLSL着色器程序而异。 The image processing thread iterates over a collection of those filter instances. 图像处理线程遍历那些过滤器实例的集合。 GetEffectResult() is only called when the image needs to be downloaded from video memory to system memory. 仅当需要将图像从视频内存下载到系统内存时,才调用GetEffectResult()。 I use a Monitor.Enter(this), because each filter instance is guaranteed to exist only once in the filter chain. 我使用Monitor.Enter(this),因为保证每个过滤器实例在过滤器链中仅存在一次。

To set up and configure the filters, I have a UI which displays the output of every filter in the filter chain. 为了设置和配置过滤器,我有一个UI,它显示过滤器链中每个过滤器的输出。 The filter instances are encapsulated by filter models, which are consumed by a WPF UI. 筛选器实例由筛选器模型封装,由WPF UI使用。

internal abstract class FilterModelBase : DependencyObject
{
    private WriteableBitmap preview;

    private static readonly DependencyPropertyKey PreviewPropertyKey = DependencyProperty.RegisterReadOnly("Preview",
        typeof(ImageSource), typeof(FilterModelBase), new PropertyMetadata());

    // The WPF window contains an Image control, which binds to this property.
    public static readonly DependencyProperty PreviewProperty = PreviewPropertyKey.DependencyProperty;

    public ImageSource Preview
    {
        get { return (ImageSource)GetValue(PreviewProperty); }
        private set { SetValue(PreviewPropertyKey, value); }
    }

    // The underlying filter.
    public IFilter Filter
    {
        get { return this.filter; }
    }

    protected FilterModelBase(IEventAggregator eventAggregator, IFilter filter)
    {
        Check.NotNull(filter, "filter");
        this.EventAggregator = eventAggregator;

        this.filter = filter;
    }

    // Updates the filter output preview.
    public virtual void Refresh(Dispatcher dispatcher)
    {
        if (!dispatcher.CheckAccess())
            dispatcher.Invoke(new Action(() => Refresh(dispatcher)));
        else
        {
            ImageInfo filterImage = null;

            Monitor.Enter(this.filter);

            if (this.filter != null && this.filter.LastResults.Count > 0)
                filterImage = this.filter.LastResults.ElementAtOrDefault(0);

            if (filterImage != null)
            {
                this.preview.WritePixels(new Int32Rect(0, 0, filterImage.Width, filterImage.Height),
                    filterImage.ImageBytes, filterImage.Width * filterImage.Channels, 0);
            }

            Monitor.Exit(this.filter);
        }
    }

The Refresh() method of each filter model instance is repeatedly called by the UI thread via a Timer. UI线程通过计时器重复调用每个过滤器模型实例的Refresh()方法。

Every now and then, I get an ArgumentOutOfRangeException on the following line: 不时地,我在下面的行上收到ArgumentOutOfRangeException:

filterImage = this.filter.LastResults.ElementAtOrDefault(0);

However, when I inspect the LastResults property, it contains one element, just like it should. 但是,当我检查LastResults属性时,它就像应该包含一个元素。 How is it possible that an ArgumentOutOfRangeException is raised, even though the debugger says that the Collection does, in fact, contain exactly one item and I always access the first item in the collection? 即使调试器说Collection实际上确实包含一个项目,而我始终访问该集合中的第一个项目,也可能引发ArgumentOutOfRangeException?

The property is re-evaluated by the debugger after the exception after has been thrown. 调试器的属性被重新评估异常后已被抛出之后 Probably the element has been inserted by another thread while the visual studio was halting everything for the debugger. 元素可能是在Visual Studio暂停调试器的所有操作时由另一个线程插入的。

HTH HTH

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当多线程时,循环索引超出范围ArgumentOutOfRangeException - For loop index out of range ArgumentOutOfRangeException when multithreading LINQ | ArgumentOutOfRangeException:索引超出范围 - LINQ | ArgumentOutOfRangeException: Index was out of range Unity3D ArgumentOutOfRangeException:索引超出范围 - Unity3D ArgumentOutOfRangeException: Index was out of range System.ArgumentOutOfRangeException:索引超出范围 - System.ArgumentOutOfRangeException: Index was out of range C#-ArgumentOutOfRangeException:索引超出范围-2种形式 - c# - ArgumentOutOfRangeException: Index was out of range - 2 Forms System.ArgumentOutOfRangeException:&#39;索引超出范围。 必须为非负数,并且小于集合的大小。” - System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.' ArgumentOutOfRangeException-索引超出范围。 必须为非负数且小于集合的大小 - ArgumentOutOfRangeException - index was out of range. Must be non-negative and less than the size of the collection 错误:System.ArgumentOutOfRangeException:索引超出范围。 必须为非负数且小于集合的大小 - Error: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection System.ArgumentOutOfRangeException:索引超出范围。 必须是非负的并且小于集合的大小。 参数名称:索引 - System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index System.ArgumentOutOfRangeException 索引超出范围。 必须是非负数且小于集合的大小。 参数名称:索引 - System.ArgumentOutOfRangeException Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM