我希望每个玩家都有一个线程来猜测一个数字。 但现在我每次创建一个线程并获得内存不足异常。 怎么解决?如何让一个线程猜数字直到获胜。 我想拥有与玩家一样多的线程并执行该功能直到有人获胜。
static void Main(string[] args)
{
object lockObject = new object();
bool isGameOver = false;
int weightOfBasket = Game.SetWeightForBasket();
Console.WriteLine("Real weight : " + weightOfBasket);
Console.WriteLine("Count of players in this game?");
var countOfPlayers = Convert.ToInt32(Console.ReadLine());
var players = new List<IPlayer>();
for (int i = 0; i < countOfPlayers; i++)
{
IPlayer player = null;
Console.WriteLine("Player's name:");
string playerName = Console.ReadLine();
Console.WriteLine("Player's type:");
string playerType = Console.ReadLine();
bool isExist = playerType != null && Enum.IsDefined(typeof(Game.Type), value: playerType);
if (isExist)
{
Type type = Type.GetType("TestTask_game." + playerType + "Player");
if (type != null)
{
player = (IPlayer)Activator.CreateInstance(type);
}
if (player != null)
{
player.Name = playerName;
player.Type = playerType;
players.Add(player);
}
}
}
while (!isGameOver)
{
Parallel.ForEach(players, new ParallelOptions(),
(player, i, j) =>
{
ThreadPool.QueueUserWorkItem(o => TryToGuess(player, weightOfBasket, out isGameOver, ref lockObject));
});
}
FindClosestToWinPlayer(players, weightOfBasket);
Console.ReadLine();
}
private static void TryToGuess(IPlayer player, int weightOfBasket, out bool IsWinner, ref object objectToLock)
{
lock (objectToLock)
{
if (_overallAmountOfAttempts == Game.AttemptsLimit)
{
IsWinner = true;
Thread.CurrentThread.Join();
return;
}
_overallAmountOfAttempts++;
int numberToGuess = player.GetNumberToGuess();
Game.AllNumberAttempts.Add(numberToGuess);
Console.WriteLine("Number is " + numberToGuess + "?");
Console.WriteLine("Attempt was made by " + player.Name);
if (numberToGuess == weightOfBasket)
{
Console.WriteLine(player.Name + " is a winner. Count of attempts = " + player.CountOfAttempts);
IsWinner = true;
Thread.CurrentThread.Join();
}
else
{
int delta = weightOfBasket - numberToGuess;
Thread.Sleep(Math.Abs(delta) * 1000);
IsWinner = false;
}
Console.WriteLine(_overallAmountOfAttempts);
}
}
答案 0 :(得分:1)
您需要仔细考虑多线程是否是您需要的,大部分时间都不是。这是一个相当复杂的主题,在最好的时候很难做到。
在你的while循环中你几乎不断地创建新线程,据我所知,在while循环期间条件永远不会变为false。此外,您在同一个对象上锁定了TryToGuess函数,这使得多线程无论如何都是无意义的 - 一次只有一个线程会进入锁定。
如果你真的确定你必须有多线程,那么这里更好的方法是为每个玩家只创建一次线程,然后让它们运行完成并在它们运行时同步它们。此外,使用Tasks或其他更高级别的抽象而不是手动处理多线程。
编辑:无论如何这一切似乎都是一个高度连续的过程 - 玩家轮流,只有一个控制台......这就是为什么我说多线程可能不是正确的方法。
编辑编辑:但是如果你真的真的想要使用多线程,我想,为了好玩或学习,你必须考虑到玩家线程和主线程之间需要进行大量的通信。他们需要知道轮到他们的时候,他们需要回答玩家是否赢了。因此,我能想到的一个合理方法是为每个玩家设置信号量,并在玩家轮到时发出信号,然后该线程运行,然后主线程检查一些共享状态以查看是否应停止(在每个玩家之后)或者在一个转弯之后),这意味着主线程需要等到玩家线程完成一个转弯。我真的没有看到不会破坏多线程目的的替代方案,抱歉:)