我正在创建一个应用程序,需要在新线程中完成一些工作并将结果保存到静态列表,然后线程自然死掉。这个额外的线程只有一个实例在执行时,所以当负责创建线程查找线程的函数已经工作时,它应该返回。
在创建我的appliaction时,我在msdn上使用了这个指南:http://msdn.microsoft.com/en-us/library/7a2f3ay4%28v=vs.80%29.aspx
本指南说:
// Create the thread object. This does not start the thread.
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
// Start the worker thread.
workerThread.Start();
Console.WriteLine("main thread: Starting worker thread...");
// Loop until worker thread activates.
while (!workerThread.IsAlive);
// Put the main thread to sleep for 1 millisecond to
// allow the worker thread to do some work:
Thread.Sleep(1);
所以我在我的应用中使用了这段代码:
if (TibiaControl.PathFinder.PathFinderThread != null && TibiaControl.PathFinder.PathFinderThread.IsAlive)
return false;
TibiaControl.PathFinder Finder = new TibiaControl.PathFinder(targetX, targetY);
TibiaControl.PathFinder.PathFinderThread = new Thread(new ThreadStart(Finder.FindPath));
TibiaControl.PathFinder.PathFinderThread.Start();
SystemControl.DebugMessage(0, "_findPath -- 1");
while (!TibiaControl.PathFinder.PathFinderThread.IsAlive) ;
Thread.Sleep(1);
SystemControl.DebugMessage(0, "_findPath -- 2");
但是当以高频率执行此功能时(例如每20-30ms一次)会发生我的应用程序卡住
while (!TibiaControl.PathFinder.PathFinderThread.IsAlive) ;
行和主线程陷入无限循环(好像线程已经在while循环发生之前完成了它的工作)。我该如何解决这个问题?
答案 0 :(得分:2)
我认为您可能盲目地复制了您不需要的示例中的一些代码:
while (!TibiaControl.PathFinder.PathFinderThread.IsAlive) ;
Thread.Sleep(1);
他们这样做的原因是为了证明他们的RequestStop方法的有用性。
答案 1 :(得分:1)
我不会将该代码用作任何有用应用程序的源代码。首先,线程有更好的方法可以等待。例如,ManualResetEventSlim
。其次,从您发布的代码中很难说IsAlive
是volatile
。那么,甚至在x86系统中,它确实没有做任何事情。特殊代码。我建议使用更安全,更明确的线程安全值读取形式。例如:
while (0 == Interlocked.Read(ref workerThread.IsAlive));
这意味着更改创建一个新的变量IsAlive 到作为long。但是,在一个单独的CPU系统中,你只使用了一个CPU而且只有很少的机会让其他线程有机会使用它。你应该控制其他线程:
while (0 == Interlocked.Read(ref workerThread.IsAlive)) Thread.Sleep(1);
但是,我认为从开始示例代码是一个坏主意。试着找出你需要做什么,并详细说明......
有关详细信息,请参阅http://msdn.microsoft.com/en-us/magazine/jj863136.aspx和http://msdn.microsoft.com/en-us/magazine/jj883956.aspx
答案 2 :(得分:0)
结合IsAlive循环并查询ThreadState:
while (!myThread.IsAlive
&& myThread.ThreadState != ThreadState.Stopped
&& myThread.ThreadState != ThreadState.Aborted)
{}
这避免了线程在启动后立即停止的情况下的无限循环