我试图了解.Net中的线程概念。 我无法使用Yield()方法。当我被10整除时,我希望控件转到并行线程。
请帮忙。
以下是我的示例代码:
class ThreadTest
{
//Index i is declared as static so that both the threads have only one copy
static int i;
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
i = 0;
//Start thread Y
t.Start();
//Do something on the main thread.
for (; i < 100; i++)
{
if (i % 10 == 0)
{
//Simulate Yield() function
Thread.Sleep(0);
Console.WriteLine("The X thread");
}
Console.Write(i + ":X ");
}
Console.ReadKey(true);
}
static void WriteY()
{
for (; i < 100; i++)
{
if (i % 10 == 0)
{
//Simulate Yield() function
Thread.Sleep(0);
Console.WriteLine("The Y thread");
}
Console.Write(i + ":Y ");
}
}
}
我收到编译时错误:
System.Threading.Thread不包含'Yield'的定义
Tudor回答。此方法仅适用于.Net 4.0及更高版本。
理想情况下,我希望一个线程启动,并希望每个线程执行10个递增的i。使用我当前的方法,我得到所有'X'或全部'Y'。
修改 随着Tudor和TheHe的输入 - 我已经能够得到替代的X和Y.问题的关键是使用锁定对象。但是这段代码的输出是不可预测的。
答案 0 :(得分:2)
Thread.Yield
只会让调度程序选择一个可以运行的其他线程:
使调用线程产生执行到另一个线程 准备在当前处理器上运行。操作系统选择 要屈服的线程。
如果您的应用程序中的其他线程也在等待该锁定,您可以获得所需的一切,它们将无法运行。
顺便说一句,Yield
是.NET 4.0+方法。确保您没有定位到早期版本。
修改:IMO,做你想做的事情应该使用事件:
class Test
{
//Index i is declared as static so that both the threads have only one copy
static int i;
static AutoResetEvent parentEvent = new AutoResetEvent(true);
static AutoResetEvent childEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
i = 0;
//Start thread Y
t.Start();
// Print X on the main thread
parentEvent.WaitOne();
while (i < 100)
{
if (i % 10 == 0)
{
childEvent.Set();
parentEvent.WaitOne();
}
Console.Write(i + ":Y ");
i++;
}
t.Join();
}
static void WriteY()
{
childEvent.WaitOne();
while (i < 100)
{
if (i % 10 == 0)
{
parentEvent.Set();
childEvent.WaitOne();
}
Console.Write(i + ":X ");
i++;
}
}
}
答案 1 :(得分:2)
忘记Thread.Yield
;这与你想要做的事情无关。最终,您有一个lock
,它使用Monitor
来同步访问权限。在lock
内,您的线程只能访问。你需要做的是暂时放弃锁;你这样做的方式是使用Monitor.Wait
。但是,如果你Wait
,你也会进入“等待”队列而不是“就绪”队列,所以为了确保每个线程得到关注,我们还需要Pulse
,在Wait
之前,也在最后(为了确保两个线程都有机会退出)。我们走了:
using System.Threading;
using System;
class ThreadTest
{
//Index i is declared as static so that both the threads have only one copy
static int i;
//The lock object
static readonly object locker = new object();
static void Main(string[] args)
{
Thread t = new Thread(WriteY);
i = 0;
//Start thread Y
t.Start();
lock (locker)
{
// Print X on the main thread
for (; i < 100; i++)
{
if (i % 10 == 0)
{
Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
Monitor.Wait(locker); // relinquish the lock, and wait for a pulse
Console.WriteLine("The X thread");
}
Console.Write(i + ":X ");
}
Monitor.PulseAll(locker);
}
Console.ReadKey(true);
}
static void WriteY()
{
lock (locker)
{
for (; i < 100; i++)
{
if (i % 10 == 0)
{
Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
Monitor.Wait(locker); // relinquish the lock, and wait for a pulse
Console.WriteLine("The Y thread");
}
Console.Write(i + ":Y ");
}
Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
}
}
}
答案 2 :(得分:1)
从我的角度来看,你在当前线程中锁定“locker”并希望将当前任务交给其他线程...... 锁是由第一个线程一直保持 - 它不能工作?!
如果要使用多个线程,则必须手动锁定对象...