这个问题在这里已有答案:

大家好,我运行我的应用程序时有这个例外。 我工作.net 3.5所以我不能使用Task

不支持在sta线程上使用多个句柄的waitall

这是代码: -

private void ThreadPopFunction(ContactList SelectedContactList, List<User> AllSelectedUsers)
{
        int NodeCount = 0;

        AllSelectedUsers.EachParallel(user =>
        {
            NodeCount++;
            if (user != null)
            {
                if (user.OCSEnable)
                {
                    string messageExciption = string.Empty;
                    if (!string.IsNullOrEmpty(user.SipURI))
                    {
                        //Lync.Lync.Lync lync = new Lync.Lync.Lync(AdObjects.Pools);
                        List<Pool> myPools = AdObjects.Pools;
                        if (new Lync.Lync.Lync(myPools).Populate(user, SelectedContactList, out messageExciption))
                        {
                        }
                    }
                }
            }
        });
}

这是我用来处理多线程的扩展方法

public static void EachParallel<T>(this IEnumerable<T> list, Action<T> action)
{
    // enumerate the list so it can't change during execution
    // TODO: why is this happening?
    list = list.ToArray();
    var count = list.Count();

    if (count == 0)
    {
        return;
    }
    else if (count == 1)
    {
        // if there's only one element, just execute it
        action(list.First());
    }
    else
    {
        // Launch each method in it's own thread
        const int MaxHandles = 64;
        for (var offset = 0; offset <= count/MaxHandles; offset++)
        {
            // break up the list into 64-item chunks because of a limitiation in WaitHandle
            var chunk = list.Skip(offset*MaxHandles).Take(MaxHandles);

            // Initialize the reset events to keep track of completed threads
            var resetEvents = new ManualResetEvent[chunk.Count()];

            // spawn a thread for each item in the chunk
            int i = 0;
            foreach (var item in chunk)
            {
                resetEvents[i] = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(new WaitCallback((object data) =>
                {
                    int methodIndex =
                        (int) ((object[]) data)[0];

                    // Execute the method and pass in the enumerated item
                    action((T) ((object[]) data)[1]);

                    // Tell the calling thread that we're done
                    resetEvents[methodIndex].Set();
                }), new object[] {i, item});
                i++;
            }

            // Wait for all threads to execute
            WaitHandle.WaitAll(resetEvents);
        }
    }
}

如果你能帮助我,我将非常感谢你的支持

===============>>#1 票数:2

好的,当您使用.Net 3.5时,您无法使用.Net 4.0中引入的TPL。

STA线程与否,在您的情况下有一种比WaitAll更简单/有效的方法。 你可以简单地拥有一个计数器和一个独特的WaitHandle 这是一些代码(现在无法测试,但应该没问题):

// No MaxHandle limitation ;)
for (var offset = 0; offset <= count; offset++)
{
    // Initialize the reset event
    var resetEvent = new ManualResetEvent();

    // Queue action in thread pool for each item in the list
    int counter = count;
    foreach (var item in list)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback((object data) =>
                      {
                          int methodIndex =
                              (int) ((object[]) data)[0];

                          // Execute the method and pass in the enumerated item
                          action((T) ((object[]) data)[1]);

                          // Decrements counter atomically
                          Interlocked.Decrement(ref counter);

                          // If we're at 0, then last action was executed
                          if (Interlocked.Read(ref counter) == 0)
                          {
                              resetEvent.Set();
                          }
                      }), new object[] {i, item});
    }

    // Wait for the single WaitHandle
    // which is only set when the last action executed
    resetEvent.WaitOne();
}

另外FYI, ThreadPool.QueueUserWorkItem每次调用时都不会产生一个线程(我之所以说这是因为注释“为块中的每个项目生成一个线程”)。 它使用一个线程池,因此它主要重用现有的线程。

===============>>#2 票数:0

对于像我这样的人,谁需要使用这些例子。 ken2k的解决方案非常好,它可以正常工作,但有一些更正(他说他没有测试它)。 这是ken2k的工作示例(为我工作):

// No MaxHandle limitation ;)
for (var offset = 0; offset <= count; offset++)
{
    // Initialize the reset event
    var resetEvent = new ManualResetEvent(false);

    // Queue action in thread pool for each item in the list
    long counter = count;
    // use a thread for each item in the chunk
    int i = 0;
    foreach (var item in list)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback((object data) =>
                      {
                          int methodIndex =
                              (int) ((object[]) data)[0];

                          // Execute the method and pass in the enumerated item
                          action((T) ((object[]) data)[1]);

                          // Decrements counter atomically
                          Interlocked.Decrement(ref counter);

                          // If we're at 0, then last action was executed
                          if (Interlocked.Read(ref counter) == 0)
                          {
                              resetEvent.Set();
                          }
                      }), new object[] {i, item});
    }

    // Wait for the single WaitHandle
    // which is only set when the last action executed
    resetEvent.WaitOne();
}

===============>>#3 票数:0

实际上有一种方法可以在.net 3.5中使用(至少很好的一部分)TPL。 有一个为Rx-Project完成的后退。

你可以在这里找到它: http//www.nuget.org/packages/TaskParallelLibrary

也许这会有所帮助。

  ask by Eslam Elmoawen translate from so

未解决问题?本站智能推荐:

5回复

不支持STA线程上的多个句柄的WaitAll

为什么我收到此错误消息? “不支持在STA线程上使用多个句柄的WaitAll。” 我应该使用[MTAThreadAttribute] attribut吗? 更新:无法使用WPF应用程序! 注意:它的错误是在WaitHandle.WaitAll(doneEvents)行;
2回复

NUnit控制台出错:“不支持STA线程上多个句柄的WaitAll”

与此问题类似,我升级到NUnit 2.6版,并开始出现线程错误。 不支持STA线程上的多个句柄的WaitAll 测试在NUnit GUI下运行正常,但在控制台版本上失败。
3回复

STA线程异常传播

我有一个必须作为STA运行的函数,我想将其异常传播给调用线程。 这里是: 将STA属性置于“MainFunction”上不是一个选项。 我注意到如果我正在使用Task,尝试catch任务join会将异常传播给调用线程,但是我不能指定运行任务作为STA。 问题是如何在例子ablo
2回复

使用SerialPort和C#中的线程“关闭了安全句柄”

大家下午好! 我有这个线程化的SerialPort包装器,它从串行端口读取一行。 这是我的线程代码。 当我调用myThread.Abort(); 我得到一个例外(没有代码的行或引用)“安全句柄已关闭”。 谁能发现我做错了什么? 谢谢。 顺便说一下,我有一个Start(
1回复

跨线程操作:调用多个文本框[重复]

这个问题在这里已有答案: 如何从其他线程更新GUI? 47个答案 我不确定我的标题是否正确,因为我真的不知道我在做什么。 我正在Visual Studio中创建一个表单,它通过serialPort与arduino进行通信。 在表单中我有大约9个文本框需
1回复

在多个线程中使用WebBrowser时发生访问冲突

我在多个线程中使用WebBrowser,但是,在执行了某些操作(从50到10000+)之后,我遇到了访问冲突异常。 代码的相关部分: 启动线程: 处理线程: 通常有2至8个这样的线程同时运行。 我不断收到访问冲突 webBrowser.Document
1回复

使用线程池对后台线程进行异常处理

我正在处理的应用程序使用线程池。 这是基本的伪代码。 在主线程上 “Component.GetObject”将基本上使用Yield return返回CLR对象。 此对象需要由线程上的两个其他组件处理。 所以我们调用提供回调方法的线程池(将调用这两个组件)。 如果在生成的
3回复

ThreadAbortException与C#中的graceful事件句柄退出

当中止线程的执行时,我总是怀疑优雅退出与事件处理程序,如下所示: 并使用事件来通知线程它必须终止 或者只是处理ThreadAbortException来完成线程...... 我通常倾向于使用ThreadAbortException方法,因为它可以被处理但是它会在catch块
2回复

使用线程插入数据时引发错误抛出异常

我在winform中使用线程时遇到问题。 调试程序时出现错误。 启动程序时,我的应用程序引发异常。 我定义的class RunInUIThread是: 并在RunInUIThread方法中,例如: 为什么我的代码不起作用。 有人可以解释我以及如何解决问题?
3回复

使用MessageBox在多线程应用程序中显示异常信息

嗨,我正在使用winform并尝试使用MessageBox进行异常处理。 这里奇怪的是,MessageBox只在主窗体(下面代码中的“Form1”)关闭后出现。 什么是使用MessageBox进行异常处理的更好方法? ...所以我在UI线程中为MessageBox-ing添加了