C# 如何在一个线程中多次执行smth直到成功?
我想让每个玩家都有一条线索来猜一个数字。 但现在我每次都创建一个线程,并得到一个内存不足异常。 如何修复它?如何使一个线程猜测数字,直到获胜。 我希望有尽可能多的线程作为球员和执行功能,直到有人赢了C# 如何在一个线程中多次执行smth直到成功?,c#,.net,multithreading,parallel-processing,C#,.net,Multithreading,Parallel Processing,我想让每个玩家都有一条线索来猜一个数字。 但现在我每次都创建一个线程,并得到一个内存不足异常。 如何修复它?如何使一个线程猜测数字,直到获胜。 我希望有尽可能多的线程作为球员和执行功能,直到有人赢了 static void Main(string[] args) { object lockObject = new object(); bool isGameOver = false; int weightOfBasket = Game.
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);
}
}
static void Main(字符串[]args)
{
对象锁定对象=新对象();
bool-isGameOver=false;
int-weightOfBasket=Game.setweightofBasket();
Console.WriteLine(“实际重量:+箱子重量”);
Console.WriteLine(“此游戏中的玩家数?”);
var countOfPlayers=Convert.ToInt32(Console.ReadLine());
var players=新列表();
对于(int i=0;i
{
QueueUserWorkItem(o=>TryToGuess(播放器,盒子的重量,out-isGameOver,ref-lockObject));
});
}
FindClosestToInplayer(玩家、背包重量);
Console.ReadLine();
}
私有静态void TryToGuess(IPlayer玩家,背包的整数权重,out bool IsWinner,ref object objectToLock)
{
锁定(对象锁定)
{
if(_overallAmountOfAttempts==Game.AttemptsLimit)
{
IsWinner=true;
Thread.CurrentThread.Join();
返回;
}
_总尝试次数++;
int numberToGuess=player.GetNumberToGuess();
Game.AllNumberAttempts.Add(numberToGuess);
Console.WriteLine(“数字为“+numberToGuess+”?”);
Console.WriteLine(“尝试由“+player.Name”进行);
if(numberToGuess==箱子的重量)
{
Console.WriteLine(player.Name+”是赢家。尝试次数=“+player.CountOfAttempts”);
IsWinner=true;
Thread.CurrentThread.Join();
}
其他的
{
int delta=箱子的重量-数字猜测;
线程睡眠(数学绝对值(增量)*1000);
IsWinner=false;
}
控制台写入线(_overallAmountOfAttempts);
}
}
您需要仔细考虑多线程是否是您所需要的,大多数情况下并非如此。这是一个相当复杂的问题,在最好的时候很难做到正确
在while循环中,您几乎一直在创建新线程,据我所知,在while循环中,条件永远不会变为false。此外,您在同一对象上锁定了TryToGuess函数,这使得多线程毫无意义——一次只有一个线程会进入锁
如果您真的决定必须使用多线程,这里更好的方法是只为每个播放器创建一次线程,然后让它们运行到完成,并在运行时同步它们。此外,使用任务或其他更高级别的抽象,而不是手动处理多线程
编辑:不管怎么说,这似乎都是一个高度串行化的过程-玩家轮换,只有一个控制台。。。这就是为什么我说多线程可能不是正确的方法
编辑:但是如果你真的想使用多线程,为了好玩或者学习,我想,你必须考虑到在播放器线程和主线程之间需要大量的通信。他们需要知道轮到他们的时候,他们需要回答球员是否赢了。所以我能想到的一个合理的方法是给每个玩家发信号,当轮到玩家时发信号,然后线程运行,然后主线程检查一些共享状态,看它是否应该停止(在每个玩家之后或者在一个回合之后),这意味着主线程需要等待,直到播放器线程完成一个回合。我真的看不到不违背多线程目的的替代方案,抱歉:)我完全不知道如何在一个线程中多次运行函数,直到成功?您可以在while循环或类似的方式中运行它,与任何其他代码一样。例如
while(true){mySemaphore.WaitOne();/*do stuff*/mySemaphore.Release();if(condition)break;}
(我只是不假思索地键入了这个,所以请不要把它作为最佳实践的示例)