.NET多线程问题

6
有没有任何本质上的区别,这段代码:
ThreadStart starter = new ThreadStart(SomeMethod);
starter.Invoke();

还有这个呢?

ThreadStart starter = new ThreadStart(SomeMethod);
Thread th = new Thread(starter);
th.Start();

或者第一个是在当前线程上调用该方法,而第二个是在新线程上调用它?

3
你实际上并没有提出与线程相关的问题。你问题的核心是:“Delegate.Invoke方法是做什么用的?”回答这个问题,你就会得到你的答案。 - Kennet Belenky
无论如何,如果您可以访问它,您应该忘记Thread API并选择Tasks API :) - Francisco Noriega
2个回答

13
它们不相同。
调用new ThreadStart(SomeMethod).Invoke()将使用迟绑定在当前线程上执行方法。这比new ThreadStart(SomeMethod)()要慢得多,而后者又比SomeMethod()稍微慢一点。
调用new Thread(SomeMethod).Start()将创建一个新线程(具有自己的堆栈),在该线程上运行该方法,然后销毁该线程。
调用ThreadPool.QueueUserWorkItem(delegate { SomeMethod(); })(您没有提到)将在线程池中在后台运行该方法,线程池是由.Net自动管理,您可以在其中运行代码的一组线程。使用线程池比创建新线程便宜得多。
调用BeginInvoke(您也没提到)也会在线程池中在后台运行该方法,并将有关方法结果的信息保留,直到您调用EndInvoke。(在调用BeginInvoke后,您必须调用EndInvoke
总的来说,最好的选择是ThreadPool.QueueUserWorkItem

1
没有一个选项比其他选项更好这种说法并不完全正确。它们有不同的用途。线程池线程用于高周转、有限工作项。新线程是当你需要一个新线程时使用。(然而,我不是那个给你点踩的人) - Kennet Belenky
@Kennet:这就是为什么我写了 总的来说。然而,只有在你需要 Thread 对象、需要 STA 或者它将会运行很长时间时,你才应该创建一个新线程。此外,我的回答是在其被踩之前写的。 - SLaks
谢谢,SLaks。ThreadPool正是我想要的——我一直在创建新线程来重复执行短暂的任务,而ThreadPool似乎更适合这种情况。 - MusiGenesis
线程池很好用,但它暴露了一个不同的问题。基本上,我正在使用这些线程来加载音频缓冲区并使用waveOutWrite API方法播放它们,因为您无法直接从waveOut回调中调用waveOutWrite。这很好用,但现在我还需要偶尔调用waveOutGetPosition方法。显然,如果我从一个线程调用此方法,而另一个线程调用waveOutWrite(这会随机发生),我会遇到死锁并且我的应用程序会挂起。 - MusiGenesis
我认为我需要的是一个单线程,我创建一次,然后重复调用以执行waveOutWrite方法。然后我可以安全地从同一线程调用waveOutGetPosition,尽管我不确定如何做到这一点。比如说,如果我想在我的表单上点击一个按钮,获取波形位置并在标签中显示它,我该怎么做?如果我只是调用该方法,它将在UI线程上执行,这与调用waveOutWrite的线程不同。 - MusiGenesis
如果您愿意,我可以将此作为一个单独的问题来询问。 :) - MusiGenesis

3

如果SLaks的回答不是完全清晰明了的:

第一个是在当前线程上调用方法,而第二个是在新线程上调用方法吗?

是的。


有时候太多信息会让人感到不知所措,因此我提供了直接回答问题的选项。顺便说一下,我已经给你的回答点了赞。 - Foole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接