c#thread从调试器启动,但不会独立启动

时间:2022-09-02 20:47:50

I've got a small app that searches for and stores the names of a large number of files at start-up. I'm splitting this search into several Thread objects that each search one directory, and push results back to the main thread.

我有一个小应用程序,在启动时搜索并存储大量文件的名称。我将这个搜索分成几个Thread对象,每个对象搜索一个目录,然后将结果推送回主线程。

When the app loads, I go through each thread and load it:

当应用程序加载时,我会遍历每个线程并加载它:

foreach(Thread t in m_threads)
{
    t.Start();
    while(!t.IsAlive){}
}

When I begin this app in the debugger, it loads and the threads quickly find all the files. However if I start outside the debugger it freezes. Attaching the debugger to the process I can see that IsAlive never returns true.

当我在调试器中开始这个应用程序时,它会加载并且线程会快速找到所有文件。但是,如果我在调试器外面启动它会冻结。将调试器附加到进程我可以看到IsAlive永远不会返回true。

I'm new to C# threading so does anyone have any idea what's going wrong, or how I can more easily debug what's happening?

我是C#线程的新手,所以有谁知道出了什么问题,或者我怎么能更容易地调试正在发生的事情?

7 个解决方案

#1


It may not be exactly related to why things are freezing, but your implementation is quite questionable. You enumerate over a collection of threads, start each one, but then block until the thread is finished? I think what you may have meant to do is start all threads, then block until all threads have finished. (Note: This is assuming you meant to write: "while(t.IsAlive) {}", since waiting for the thread to start makes even less sense.)

它可能与事情冻结的原因并不完全相关,但你的实现是非常值得怀疑的。您枚举一组线程,启动每个线程,但然后阻塞直到线程完成?我认为你可能要做的是启动所有线程,然后阻塞直到所有线程都完成。 (注意:这假设您打算写:“while(t.IsAlive){}”,因为等待线程启动的意义更小。)

As for the freezing, we may need to see the rest of the code. Since you said you are new to C# threading, and looking at what you did above, I am assuming you are also new to threading, which means there could be many places that a problem can rise.

至于冻结,我们可能需要查看其余的代码。既然你说你是C#线程的新手,并且看看你上面做了什么,我假设你也是线程新手,这意味着可能会有很多地方出现问题。

#2


The thread may have finished processing before your check against IsAlive.

在对IsAlive进行检查之前,线程可能已经完成处理。

WHy are you waiting by checking the IsAlive flag anyway?

你还等什么,等一下检查IsAlive标志?

Why not, instead, fire up all the threads, then in another loop, call Join() to wait for the threads to finish? No need to check "IsAlive".

相反,为什么不启动所有线程,然后在另一个循环中调用Join()以等待线程完成?无需检查“IsAlive”。

Even better, why not use the ThreadPool instead of firing up a stack of threads yourself?

更好的是,为什么不使用ThreadPool而不是自己激活一堆线程?

#3


You perhaps mean IsAlive() "never returns false".

你可能意味着IsAlive()“永远不会返回false”。

Well, if so, that's because your threads continue to execute infinitely. May be the method you're calling in these threads has an infinite loop or something.

好吧,如果是这样,那是因为你的线程继续无限执行。可能是你在这些线程中调用的方法有一个无限循环或其他东西。

#4


It appears I mis-understood the code I cut-and-paste'd to create my threading code. I assumed the while(!t.isAlive){} line was blocking until the thread could properly start itself, and thought it was necessary administration.

看来我误解了我剪切和粘贴的代码来创建我的线程代码。我假设while(!t.isAlive){}行被阻塞,直到线程可以正常启动,并认为这是必要的管理。

I removed that line and the app launches fine out of the debugger. I join the threads later in the code, so that should be it.

我删除了该行,应用程序从调试器中启动。我稍后在代码中加入了线程,所以应该是它。

Is there a "NEWB!" tag? :)

有没有“NEWB!”标签? :)

#5


With the code you provided above, It seems to me that you want to start the threads sequentially. If so why do you need many threads? 1 thread can do the job.

使用上面提供的代码,在我看来,您想要按顺序启动线程。如果是这样,为什么你需要很多线程? 1个线程可以完成这项工作。

EDIT: (after your answer)

编辑:(在你的答案后)

Ok. I see that you removed the questionable line.

好。我看到你删除了有问题的一行。

Even so, in your case, I would consider to use only one thread for loading these file names because you are accessing only one IO resource (the disk). Each thread is competing for this resource. Have you tried to move 1 big file in windows and then move another big file while the first is still moving? The performance of your disk decreases. Because of this I would only create one thread for each different IO resource.

即便如此,在您的情况下,我会考虑只使用一个线程来加载这些文件名,因为您只访问一个IO资源(磁盘)。每个线程都在竞争这个资源。您是否尝试在Windows中移动1个大文件,然后移动另一个大文件,而第一个仍在移动?磁盘性能下降。因此,我只为每个不同的IO资源创建一个线程。

#6


I would recommend not to hold a collection of Threads, but use Threadstarts instead. If you join them later, theres no need to wait until the Thread is running, so you while-loop is unnecessary. Make sure, your Threads are marked as Background-Threads, so they are cleaned up automatically after execution.

我建议不要持有一个Threads集合,而是使用Threadstarts。如果您以后加入它们,则无需等到Thread运行,因此您不需要while循环。确保您的线程被标记为后台线程,因此它们会在执行后自动清理。

I would do this like this: List threadStarters = new List();

我会这样做:List threadStarters = new List();

foreach (ThreadStart ts in threadStarters)
{
    Thread t = new Thread(ts);
    t.IsBackground = true;
    t.Start();
}

#7


I don't know what you are doing in your threads exactly, but I think that...

我完全不知道你在线程中做了什么,但我认为......

Multithreading + Application behaving differently with debugger attached = Race conditions

多线程+应用程序与附加调试器的行为不同=竞争条件

I am pretty sure that you got some synchronization issues.

我很确定你有一些同步问题。

#1


It may not be exactly related to why things are freezing, but your implementation is quite questionable. You enumerate over a collection of threads, start each one, but then block until the thread is finished? I think what you may have meant to do is start all threads, then block until all threads have finished. (Note: This is assuming you meant to write: "while(t.IsAlive) {}", since waiting for the thread to start makes even less sense.)

它可能与事情冻结的原因并不完全相关,但你的实现是非常值得怀疑的。您枚举一组线程,启动每个线程,但然后阻塞直到线程完成?我认为你可能要做的是启动所有线程,然后阻塞直到所有线程都完成。 (注意:这假设您打算写:“while(t.IsAlive){}”,因为等待线程启动的意义更小。)

As for the freezing, we may need to see the rest of the code. Since you said you are new to C# threading, and looking at what you did above, I am assuming you are also new to threading, which means there could be many places that a problem can rise.

至于冻结,我们可能需要查看其余的代码。既然你说你是C#线程的新手,并且看看你上面做了什么,我假设你也是线程新手,这意味着可能会有很多地方出现问题。

#2


The thread may have finished processing before your check against IsAlive.

在对IsAlive进行检查之前,线程可能已经完成处理。

WHy are you waiting by checking the IsAlive flag anyway?

你还等什么,等一下检查IsAlive标志?

Why not, instead, fire up all the threads, then in another loop, call Join() to wait for the threads to finish? No need to check "IsAlive".

相反,为什么不启动所有线程,然后在另一个循环中调用Join()以等待线程完成?无需检查“IsAlive”。

Even better, why not use the ThreadPool instead of firing up a stack of threads yourself?

更好的是,为什么不使用ThreadPool而不是自己激活一堆线程?

#3


You perhaps mean IsAlive() "never returns false".

你可能意味着IsAlive()“永远不会返回false”。

Well, if so, that's because your threads continue to execute infinitely. May be the method you're calling in these threads has an infinite loop or something.

好吧,如果是这样,那是因为你的线程继续无限执行。可能是你在这些线程中调用的方法有一个无限循环或其他东西。

#4


It appears I mis-understood the code I cut-and-paste'd to create my threading code. I assumed the while(!t.isAlive){} line was blocking until the thread could properly start itself, and thought it was necessary administration.

看来我误解了我剪切和粘贴的代码来创建我的线程代码。我假设while(!t.isAlive){}行被阻塞,直到线程可以正常启动,并认为这是必要的管理。

I removed that line and the app launches fine out of the debugger. I join the threads later in the code, so that should be it.

我删除了该行,应用程序从调试器中启动。我稍后在代码中加入了线程,所以应该是它。

Is there a "NEWB!" tag? :)

有没有“NEWB!”标签? :)

#5


With the code you provided above, It seems to me that you want to start the threads sequentially. If so why do you need many threads? 1 thread can do the job.

使用上面提供的代码,在我看来,您想要按顺序启动线程。如果是这样,为什么你需要很多线程? 1个线程可以完成这项工作。

EDIT: (after your answer)

编辑:(在你的答案后)

Ok. I see that you removed the questionable line.

好。我看到你删除了有问题的一行。

Even so, in your case, I would consider to use only one thread for loading these file names because you are accessing only one IO resource (the disk). Each thread is competing for this resource. Have you tried to move 1 big file in windows and then move another big file while the first is still moving? The performance of your disk decreases. Because of this I would only create one thread for each different IO resource.

即便如此,在您的情况下,我会考虑只使用一个线程来加载这些文件名,因为您只访问一个IO资源(磁盘)。每个线程都在竞争这个资源。您是否尝试在Windows中移动1个大文件,然后移动另一个大文件,而第一个仍在移动?磁盘性能下降。因此,我只为每个不同的IO资源创建一个线程。

#6


I would recommend not to hold a collection of Threads, but use Threadstarts instead. If you join them later, theres no need to wait until the Thread is running, so you while-loop is unnecessary. Make sure, your Threads are marked as Background-Threads, so they are cleaned up automatically after execution.

我建议不要持有一个Threads集合,而是使用Threadstarts。如果您以后加入它们,则无需等到Thread运行,因此您不需要while循环。确保您的线程被标记为后台线程,因此它们会在执行后自动清理。

I would do this like this: List threadStarters = new List();

我会这样做:List threadStarters = new List();

foreach (ThreadStart ts in threadStarters)
{
    Thread t = new Thread(ts);
    t.IsBackground = true;
    t.Start();
}

#7


I don't know what you are doing in your threads exactly, but I think that...

我完全不知道你在线程中做了什么,但我认为......

Multithreading + Application behaving differently with debugger attached = Race conditions

多线程+应用程序与附加调试器的行为不同=竞争条件

I am pretty sure that you got some synchronization issues.

我很确定你有一些同步问题。