在我们的应用程序中,我们间歇性地得到了这个异常:
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,虽然它与一个通道列表交互,但它需要引用的副本,RegisterChannel和UnregisterChannel似乎都有锁,并在一次操作中替换了这个列表。
我们被困住了。如果锁按广告显示的那样工作,并且MSDN文档是正确的(它说这个类的静态成员是线程安全),那么在这个属性中什么会导致IndexOutOfRange呢?
编辑:我成功地制作了一个小型控制台应用程序,它会间歇性地(在我的测试中每5次运行1次)抛出这个异常。我正在以.NET 4.5.2为目标在VS 2015更新1中编译。
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());这是它崩溃时的错误:
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 . . .发布于 2016-03-30 07:34:14
我们在我们的repro中确认,在代码周围添加锁可以解决问题。我们认为,当第一个线程位于ChannelServices.RegisterChannel内部,而第二个线程同时访问ChannelServices.RegisteredChannels时,问题就会发生。我们认为,这种情况只发生在第一次命中这些(当列表首次使用CrossAppDomainChannel填充时),因此可能的解决办法包括:
由于我们的使用是低音量,它可能会更简单,只是锁定整个事情。取决于您的代码,这可能是或不合适的!
https://stackoverflow.com/questions/35992245
复制相似问题