Cla*_*dia 4 c# console recursion multithreading
我想实现一个程序,显示一些在控制台上随机移动的字符,每个字符都有不同的速度.
我创建了一个递归方法,在控制台上随机移动一个字母.当我想移动两个字母时,我使用两个线程调用相同的方法.
该程序在第一分钟完美运行,但过了一段时间后,这些字母开始在控制台上出现!
我确定我的递归方法没问题(我甚至尝试创建另一种方法,这次只使用一段时间(i <100000)而不是递归.但出现了同样的错误).有人可以帮我吗?
非常感谢你.
编辑:对不起,这是一个示例代码(不考虑如果字母占据相同的位置会发生什么).字母在"体育场"上移动,它们在x轴上移动20-51,在y轴上移动5-26.
public void WriteAt(string s, int x, int y)
{
try
{
Console.SetCursorPosition(x, y);
Console.Write(s);
}
catch (ArgumentOutOfRangeException e)
{
Console.Clear();
Console.WriteLine(e.Message);
}
}
public void impresion()
{
int x = random.Next(20, 51);
int y = random.Next(5, 26);
WriteAt("A", x, y);
imprimir("A", x, y, 80);
}
public void impresion2()
{
int x = random.Next(20, 51);
int y = random.Next(5, 26);
WriteAt("E", x, y);
imprimir2("E", x, y, 20);
}
public void go()
{
Thread th1 = new Thread(impresion);
Thread th2 = new Thread(impresion2);
th1.Start(); //creates an 'A' that will move randomly on console
th2.Start(); //creates an 'E' that will move randomly on console
}
public void imprimir(string s, int x, int y, int sleep)
{
Thread.Sleep(sleep);
WriteAt(" ", x, y);
int n = random.Next(1, 5);
if (n == 1)
{
if ((x + 1) > 50)
{
WriteAt(s, x, y);
imprimir(s, x, y, sleep);
}
else
{
WriteAt(s, x + 1, y);
imprimir(s, x + 1, y, sleep);
}
}
else if (n == 2)
{
if ((y - 1) < 5)
{
WriteAt(s, x, y);
imprimir(s, x, y, sleep);
}
else
{
WriteAt(s, x, y - 1);
imprimir(s, x, y - 1, sleep);
}
}
else if (n == 3)
{
if ((x - 1) < 20)
{
WriteAt(s, x, y);
imprimir(s, x, y, sleep);
}
else
{
WriteAt(s, x - 1, y);
imprimir(s, x - 1, y, sleep);
}
}
else
{
if ((y + 1) > 25)
{
WriteAt(s, x, y);
imprimir(s, x, y, sleep);
}
else
{
WriteAt(s, x, y + 1);
imprimir(s, x, y + 1, sleep);
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
线程可能有一百万个微妙的问题 - 任何访问共享资源的东西都必须被认为是可疑的.
考虑一个移动位置跟随一个put字符不是原子的,一个线程可能会中断另一个线程导致move-move-put-put场景.实际上情况实际上比这更糟糕,因为控制序列本身受到发送到终端的多个字节的影响:因此控制序列本身可能变得腐败!
lock
在终端访问周围使用关键区域防护().本lock
应包含哪些必须的所有操作原子(不中断)就海誓山盟:
lock (foo) {
move(...)
draw(...)
}
Run Code Online (Sandbox Code Playgroud)
WriteAt
适当地适应该功能.
但是,请记住,即使有这种变化,仍然存在微妙的竞争条件,请考虑:
有了上述内容,有可能(在特定时间)E将出现在屏幕上而A不会出现.也就是说lock
,在保护对控制台的访问权限的同时,自身无法充分保护线程和控制台之间的交互.
快乐的编码.
另请参见什么是常见的并发陷阱?一些一般的提示和链接.