-1

我正在创建一个应用程序,需要在新线程中做一些工作并将结果保存到静态列表,然后线程自然死亡。一次只能执行这个附加线程的一个实例,因此当负责创建线程的函数发现线程已经工作时,它应该返回。

创建我的应用程序时,我在 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-30 毫秒一次),我的应用程序会卡住

while (!TibiaControl.PathFinder.PathFinderThread.IsAlive) ;

行和主线程陷入无限循环(好像线程在while循环发生之前已经完成了它的工作)。我该如何解决?

4

3 回答 3

2

我认为您可能从示例中盲目地复制了一些您不需要的代码:

while (!TibiaControl.PathFinder.PathFinderThread.IsAlive) ;
Thread.Sleep(1);

他们这样做的原因是为了展示他们的 RequestStop 方法的有用性。

于 2013-02-19T16:03:38.587 回答
1

我不会将该代码用作任何有用应用程序的源代码。首先,线程等待有更好的方法。例如,ManualResetEventSlim。其次,很难从您发布的代码中判断是否IsAlivevolatile. 那么,即使是在一个真正不使用特殊代码做任何事情的 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.aspxhttp://msdn.microsoft.com/en-us/magazine/jj883956.aspx

于 2013-02-19T16:01:57.660 回答
0

将 IsAlive 循环与查询 ThreadState 结合起来:

while (!myThread.IsAlive 
    && myThread.ThreadState != ThreadState.Stopped
    && myThread.ThreadState != ThreadState.Aborted)
{}

这避免了线程在启动后立即停止的情况下的无限循环

于 2017-09-29T08:53:13.737 回答