gpt4 book ai didi

c# - 尝试修改字典时出现异常

转载 作者:太空宇宙 更新时间:2023-11-03 10:29:02 26 4
gpt4 key购买 nike

我正在创建一个字典来管理线程,当我在向字典中添加一些线程后尝试清除死线程时遇到了这个异常。

using System;
using System.Collections.Generic;
using System.Threading;

namespace SysCat {
public class ThreadManager {
public static readonly ThreadManager GlobalThreadManager = new ThreadManager( );

/// <summary>
/// Initializes a new instance of the <see cref="SysCat.ThreadManager"/> class.
/// </summary>
public ThreadManager( ) {

}

/// <summary>
/// Create a new ThreadManager with all the Threads within baseTM and deinitializes baseTM
/// </summary>
public ThreadManager( ThreadManager baseTM ) {
this.threads = baseTM.threads;
baseTM.threads.Clear( );
}

private Dictionary<Guid,Thread> threads = new Dictionary<Guid, Thread>( );

/// <summary>
/// Attempts to obtain an unused ThreadID within an attempt limit
/// </summary>
/// <returns>The unused ThreadID, if found</returns>
/// <param name="attempts">The number of iterations to try.</param>
public Guid getUnusedThreadID( int attempts ) {
lock( threads ) {
Guid threadID;
int totalAttempts = attempts;
while( threads.ContainsKey( ( threadID = Guid.NewGuid( ) ) ) ) {
attempts--;
if( attempts == 0 )
throw new NoOpenThreadIDException( totalAttempts );
}
return threadID;
}
}

/// <summary>
/// Attempts to get a Thread via its ThreadID, if it exists
/// </summary>
/// <returns>The Thread</returns>
/// <param name="threadID">The ThreadID to use</param>
public Thread getThread( Guid threadID ) {
lock( threads ) {
Thread tryGet;
if( !threads.TryGetValue( threadID, out tryGet ) )
throw new ArgumentException( "Specified ThreadID does not exist in this ThreadManager" );
return tryGet;
}
}

/// <summary>
/// Attempts to get a ThreadID via the Thread
/// </summary>
/// <returns>The ThreadID</returns>
/// <param name="thread">The Thread to use</param>
public Guid getThreadID( Thread thread ) {
lock( threads ) {
if( threads.ContainsValue( thread ) ) {
foreach( Guid id in threads.Keys ) {
Thread t;
threads.TryGetValue( id, out t );
if( t.Equals( thread ) )
return id;
}
// I should never get here
return Guid.Empty;
}
else
throw new ArgumentException( "Specified Thread does not exist in this ThreadManager" );
}
}

/// <summary>
/// Adds the Thread, unless it cannot find an open ThreadID
/// </summary>
/// <returns>The ThreadID used to register the Thread</returns>
/// <param name="thread">The Thread to register</param>
public Guid addThread( Thread thread ) {
lock( threads ) {
Guid id;
try {
id = getUnusedThreadID( 500 );
}
catch( NoOpenThreadIDException e ) {
throw e;
}
threads.Add( id, thread );
return id;
}
}

/// <summary>
/// Attempts to clear all stopped and null Threads
/// </summary>
/// <returns>The number of dead Threads cleared</returns>
public int clearDeadThreads() {
int cleared = 0;
lock(threads) {
foreach( Guid id in threads.Keys ) {
Thread thread;
threads.TryGetValue( id, out thread );
if( thread == null ) {
// Does not exist, Thread is dead
cleared++;
threads.Remove( id );
continue;
}
if( !thread.IsAlive ) {
// Not alive, Thread is dead
cleared++;
threads.Remove( id );
continue;
}
}
}

return cleared;
}

public class NoOpenThreadIDException : Exception {
public NoOpenThreadIDException( int attempts )
: base( string.Format( "Unable to find an open ThreadID within the attempt limit of {0}", attempts ) ) {
}
}
}
}

我得到这个异常:System.InvalidOperationException带有消息:集合已修改;枚举操作可能不会执行

我不确定为什么会这样,如有任何帮助,我们将不胜感激。

这是我用来测试它的代码:

using System;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System.Threading;

using _TM = SysCat.ThreadManager;

namespace SysCat {
public class SysCat {
Thread T = new Thread( new ThreadStart( delegate {
while(true) Thread.Sleep(250);
} ) );
Thread T2 = new Thread( new ThreadStart( delegate {

} ) );
Thread T3 = new Thread( new ThreadStart( delegate {

} ) );
_TM.GlobalThreadManager.addThread( T );
_TM.GlobalThreadManager.addThread( T2 );
_TM.GlobalThreadManager.addThread( T3 );
Console.WriteLine( _TM.GlobalThreadManager.clearDeadThreads( ) );
Console.ReadLine( );
}
}
}

最佳答案

您不能在枚举 IEnumerable 时修改它。

你可以做一个简单的 hack 并获得你正在枚举的内容的副本,这样它的更改就不会导致 System.InvalidOperationException

例如代替

foreach( Guid id in threads.Keys) 

使用

foreach( Guid id in threads.Keys.ToList()) 

请记住,您可以使用 data structures that supports concurrency

关于c# - 尝试修改字典时出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30823192/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com