积极答复者
不支持一个 STA 线程上多个句柄的 WaitAll

问题
-
如题,我写另一个winform程序,把一些初始化的函数都加载到Form1_load事件中,其中的函数用到了线程池,为了线程同步我使用了AutoResetEvent.waitall,但是提示如上错误,我google了一下,基本上都是说要在main()前面加上<MTAThreadAttribute()> ,但是form1里面根本就没有main函数,这个该怎么弄啊?
另外,我查看了本论坛的几个类似的帖子,http://social.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/3db748bb-1e5b-4fec-a2ae-e3978361a979/ 里面提到了WaitHandle.WaitAll这个函数本身只能传递64个句柄,再多就会抛出NotSupportedException异常了,这个是不是说如果WaitHandle.waitall(AutoResetEventTest),如果AutoResetEventTest数组元素大于64的话就会异常了?如果程序需要AutoResetEventTest元素大于64个的话,该采用什么方法啊?
刚接触线程同步的内容,有点头大...
答案
-
楼主,您好,两个观点请参考:
1、.net设计规范中不建议初始化的东西放在Page_Load()里。
2、如果不仅仅想通知线程去执行,还想控制线程的执行,可以考虑用Semaphore。
Jiyuan 你好:
感谢你的建议,对于第一点,我不知道除了把初始化的内容放到page_load里以外放到哪里比较合适?是放到form的new() 里还是InitializeComponent()里?
对于第二点,我正在MSDN上找相关的示例,谢谢你的建议.
您好,不客气。初始化通常都是放在构造函数中,InitializeComponent()其实也是在构造函数中的,由于是自动产生的用来初始化界面元素的,不建议放在InitializeComponent()中。- 已标记为答案 Allen Chen - MSFTModerator 2009年9月29日 5:38
全部回复
-
Module Module1 Public Sub Main() Dim f As New Form1 f.ShowDialog() End Sub End Module '刚才通过了阿
恭喜自己5星用户达成- 已建议为答案 韦恩卑鄙 waywa 2009年9月2日 5:01
-
如题,我写另一个winform程序,把一些初始化的函数都加载到Form1_load事件中,其中的函数用到了线程池,为了线程同步我使用了AutoResetEvent.waitall,但是提示如上错误,我google了一下,基本上都是说要在main()前面加上<MTAThreadAttribute()> ,但是form1里面根本就没有main函数,这个该怎么弄啊?
另外,我查看了本论坛的几个类似的帖子,http://social.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/3db748bb-1e5b-4fec-a2ae-e3978361a979/ 里面提到了WaitHandle.WaitAll这个函数本身只能传递64个句柄,再多就会抛出NotSupportedException异常了,这个是不是说如果WaitHandle.waitall(AutoResetEventTest),如果AutoResetEventTest数组元素大于64的话就会异常了?如果程序需要AutoResetEventTest元素大于64个的话,该采用什么方法啊?
刚接触线程同步的内容,有点头大...
另外 线城池默认大小是16 应该没啥问题吧
超出cpu核心数目的线城本身就是罪过了 没啥意义的
恭喜自己5星用户达成 -
改成
For Each handle As WaitHandle In AutoResetEventTest
handle.WaitOne()
Next
http://feiyun0112.cnblogs.com/- 已建议为答案 韦恩卑鄙 waywa 2009年9月2日 5:22
-
改成
For Each handle As WaitHandle In AutoResetEventTest
handle.WaitOne()
Next
http://feiyun0112.cnblogs.com/
通过了~~!,飞云你太有才了,哈哈.
不过程序本身还有点问题,我找找原因先.
谢谢飞云,也谢谢韦恩卑鄙.你们都很热心. -
晕了,msdn上的示例也是相同的提示..
代码如下:
Imports System Imports System.Threading Module Module1 Sub Main() Dim a As New App App.Main() Console.ReadKey() End Sub End Module Public NotInheritable Class App ' Define an array with two AutoResetEvent WaitHandles. Private Shared waitHandles() As WaitHandle = _ {New AutoResetEvent(False), New AutoResetEvent(False)} ' Define a random number generator for testing. Private Shared r As New Random() <MTAThreadAttribute()> _ Public Shared Sub Main() ' Queue two tasks on two different threads; ' wait until all tasks are completed. Dim dt As DateTime = DateTime.Now Console.WriteLine("Main thread is waiting for BOTH tasks to complete.") ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0)) ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1)) WaitHandle.WaitAll(waitHandles) ' The time shown below should match the longest task. Console.WriteLine("Both tasks are completed (time waited={0})", _ (DateTime.Now - dt).TotalMilliseconds) ' Queue up two tasks on two different threads; ' wait until any tasks are completed. dt = DateTime.Now Console.WriteLine() Console.WriteLine("The main thread is waiting for either task to complete.") ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0)) ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1)) Dim index As Integer = WaitHandle.WaitAny(waitHandles) ' The time shown below should match the shortest task. Console.WriteLine("Task {0} finished first (time waited={1}).", _ index + 1, (DateTime.Now - dt).TotalMilliseconds) End Sub 'Main Shared Sub DoTask(ByVal state As [Object]) Dim are As AutoResetEvent = CType(state, AutoResetEvent) Dim time As Integer = 1000 * r.Next(2, 10) Console.WriteLine("Performing a task for {0} milliseconds.", time) Thread.Sleep(time) are.Set() End Sub 'DoTask End Class 'App ' This code produces output similar to the following: ' ' Main thread is waiting for BOTH tasks to complete. ' Performing a task for 7000 milliseconds. ' Performing a task for 4000 milliseconds. ' Both tasks are completed (time waited=7064.8052) ' ' The main thread is waiting for either task to complete. ' Performing a task for 2000 milliseconds. ' Performing a task for 2000 milliseconds. ' Task 1 finished first (time waited=2000.6528). 不支持一个 STA 线程上多个句柄的 WaitAll
补充一下,以上是放在控制台程序中的,运行环境是VB2005,不会是我的IDE某个环境变量没设置好吧??- 已编辑 picat 2009年9月2日 5:46 补充
-
楼主,您好,两个观点请参考:
1、.net设计规范中不建议初始化的东西放在Page_Load()里。
2、如果不仅仅想通知线程去执行,还想控制线程的执行,可以考虑用Semaphore。
Jiyuan 你好:
感谢你的建议,对于第一点,我不知道除了把初始化的内容放到page_load里以外放到哪里比较合适?是放到form的new() 里还是InitializeComponent()里?
对于第二点,我正在MSDN上找相关的示例,谢谢你的建议.
您好,不客气。初始化通常都是放在构造函数中,InitializeComponent()其实也是在构造函数中的,由于是自动产生的用来初始化界面元素的,不建议放在InitializeComponent()中。- 已标记为答案 Allen Chen - MSFTModerator 2009年9月29日 5:38