首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >间歇IndexOutOfRangeException在ChannelServices.RegisteredChannels中的应用

间歇IndexOutOfRangeException在ChannelServices.RegisteredChannels中的应用
EN

Stack Overflow用户
提问于 2016-03-14 15:56:43
回答 1查看 131关注 0票数 1

在我们的应用程序中,我们间歇性地得到了这个异常:

代码语言:javascript
复制
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Runtime.Remoting.Channels.ChannelServices.get_RegisteredChannels()
at ProductCacheServiceClient.getProductCacheServiceProvider(DataServiceConnectionDetails connOptions)

由于它是断断续续的,我们称之为相当多(在一个web应用程序中,所以可以并发),我想这可能是一个线程问题,但我看了一下ChannelServices.get_RegisteredChannels,虽然它与一个通道列表交互,但它需要引用的副本,RegisterChannelUnregisterChannel似乎都有锁,并在一次操作中替换了这个列表。

我们被困住了。如果锁按广告显示的那样工作,并且MSDN文档是正确的(它说这个类的静态成员是线程安全),那么在这个属性中什么会导致IndexOutOfRange呢?

编辑:我成功地制作了一个小型控制台应用程序,它会间歇性地(在我的测试中每5次运行1次)抛出这个异常。我正在以.NET 4.5.2为目标在VS 2015更新1中编译。

代码语言:javascript
复制
List<Task> tasks = new List<Task>();

for (var i = 0; i < 1000; i++)
{

    var task = Task.Run(() =>
    {
        var chanProps = new System.Collections.Hashtable();
        chanProps["name"] = "cacheServicesClient" + Guid.NewGuid().ToString();
        chanProps["username"] = "a";
        chanProps["password"] = "b";
        chanProps["domain"] = "c";

        var channelToReturn = new TcpChannel(chanProps, null, null);
        bool registered = false;
        foreach (var channelRegistered in ChannelServices.RegisteredChannels)
        {
            if (channelRegistered.ChannelName == channelToReturn.ChannelName)
            {
                registered = true;
                break;
            }
        }

        if (!registered)
        {
            ChannelServices.RegisterChannel(channelToReturn, true);
        }
    }).ContinueWith(t =>
    {
        if (t.IsFaulted && t.Exception != null)
        {
            t.Exception.Handle(e =>
            {
                Console.WriteLine(e.ToString());
                return true;
            });
        }
    });

    tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());

这是它崩溃时的错误:

代码语言:javascript
复制
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Runtime.Remoting.Channels.ChannelServices.get_RegisteredChannels()
   at ConsoleApplication1.Program.<>c.<Main>b__0_0() in C:\Work\Source\TestApps\ConsoleApplication1\Program.cs:line 28
   at System.Threading.Tasks.Task.Execute()
Press any key to continue . . .
EN

回答 1

Stack Overflow用户

发布于 2016-03-30 07:34:14

我们在我们的repro中确认,在代码周围添加锁可以解决问题。我们认为,当第一个线程位于ChannelServices.RegisterChannel内部,而第二个线程同时访问ChannelServices.RegisteredChannels时,问题就会发生。我们认为,这种情况只发生在第一次命中这些(当列表首次使用CrossAppDomainChannel填充时),因此可能的解决办法包括:

  1. 注册单个通道(要完成!)在允许任何其他线程尝试并创建通道之前
  2. 在整个代码块周围设置锁

由于我们的使用是低音量,它可能会更简单,只是锁定整个事情。取决于您的代码,这可能是或不合适的!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35992245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档