none
不支持一个 STA 线程上多个句柄的 WaitAll RRS feed

  • 问题

  •    如题,我写另一个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个的话,该采用什么方法啊?
       刚接触线程同步的内容,有点头大...
    2009年9月2日 4:14

答案

  • 楼主,您好,两个观点请参考:
    1、.net设计规范中不建议初始化的东西放在Page_Load()里。
    2、如果不仅仅想通知线程去执行,还想控制线程的执行,可以考虑用Semaphore。

         Jiyuan 你好:
         感谢你的建议,对于第一点,我不知道除了把初始化的内容放到page_load里以外放到哪里比较合适?是放到form的new() 里还是InitializeComponent()里?
         对于第二点,我正在MSDN上找相关的示例,谢谢你的建议.

    您好,不客气。初始化通常都是放在构造函数中,InitializeComponent()其实也是在构造函数中的,由于是自动产生的用来初始化界面元素的,不建议放在InitializeComponent()中。
    2009年9月2日 6:07

全部回复

  • 嘿嘿  你建立一个  Module 里面建立一个  sub Main就可以了

    在工程属性选项 把启动项设置为submain
    恭喜自己5星用户达成
    2009年9月2日 4:29
  • 哈哈,有道理,我试试先,不过下意识感觉还会有问题...

    2009年9月2日 4:30
  • 恩 submain 要记得显示主窗体哦
    恭喜自己5星用户达成
    2009年9月2日 4:32
  •    好像不行.. 工程属性窗口里面,启动窗口只能选择窗体类,没法选择模块或者submain..,我的程序是Winform的.
    2009年9月2日 4:43
  • 你要把下面的  enable application framwork 关掉才行  那个选项会生成自己的submain 取代你的  所以就不能选了
    恭喜自己5星用户达成
    2009年9月2日 4:49
  • Module Module1
        Public Sub Main()
            Dim f As New Form1
    
            f.ShowDialog()
        End Sub
    End Module
    '刚才通过了阿

    恭喜自己5星用户达成
    2009年9月2日 4:52
  • 调用没问题了,就是程序UI界面的样式都没了.

    并且在运行时又报错:在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记.
    我的main代码是这样的:
    Module Module1
        <MTAThreadAttribute()> _
        Sub Main()
            Dim f As New form1
            form1.ShowDialog()

        End Sub

    End Module
    它这个报错似乎有绕回来了..

    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星用户达成
    2009年9月2日 5:03
  • 改成
    For Each handle As WaitHandle In AutoResetEventTest
                handle.WaitOne()
            Next


    http://feiyun0112.cnblogs.com/
    2009年9月2日 5:08
    版主
  • 改成
    For Each handle As WaitHandle In AutoResetEventTest
                handle.WaitOne()
            Next


    http://feiyun0112.cnblogs.com/

    通过了~~!,飞云你太有才了,哈哈.
    不过程序本身还有点问题,我找找原因先.
    谢谢飞云,也谢谢韦恩卑鄙.你们都很热心.
    2009年9月2日 5:15
  • 你调用了支持只支持sta的 com  情况很复杂  不贴代码 也只能帮到这些了:(


    恭喜自己5星用户达成
    2009年9月2日 5:24
  • 你调用了支持只支持sta的 com  情况很复杂  不贴代码 也只能帮到这些了:(


    恭喜自己5星用户达成

       嗯,由于我的代码涉及部分公司的敏感信息,所以实在不好贴上来.不过还是十分感谢你~
    2009年9月2日 5:29
  • 晕了,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 补充
    2009年9月2日 5:43
  • 楼主,您好,两个观点请参考:
    1、.net设计规范中不建议初始化的东西放在Page_Load()里。
    2、如果不仅仅想通知线程去执行,还想控制线程的执行,可以考虑用Semaphore。
    2009年9月2日 5:49
  • 楼主,您好,两个观点请参考:
    1、.net设计规范中不建议初始化的东西放在Page_Load()里。
    2、如果不仅仅想通知线程去执行,还想控制线程的执行,可以考虑用Semaphore。

         Jiyuan 你好:
         感谢你的建议,对于第一点,我不知道除了把初始化的内容放到page_load里以外放到哪里比较合适?是放到form的new() 里还是InitializeComponent()里?
         对于第二点,我正在MSDN上找相关的示例,谢谢你的建议.
    2009年9月2日 5:54
  • 楼主,您好,两个观点请参考:
    1、.net设计规范中不建议初始化的东西放在Page_Load()里。
    2、如果不仅仅想通知线程去执行,还想控制线程的执行,可以考虑用Semaphore。

         Jiyuan 你好:
         感谢你的建议,对于第一点,我不知道除了把初始化的内容放到page_load里以外放到哪里比较合适?是放到form的new() 里还是InitializeComponent()里?
         对于第二点,我正在MSDN上找相关的示例,谢谢你的建议.

    您好,不客气。初始化通常都是放在构造函数中,InitializeComponent()其实也是在构造函数中的,由于是自动产生的用来初始化界面元素的,不建议放在InitializeComponent()中。
    2009年9月2日 6:07