Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用AutoResteEvent同步.NET线程池_C#_.net_Multithreading_Threadpool - Fatal编程技术网

C# 使用AutoResteEvent同步.NET线程池

C# 使用AutoResteEvent同步.NET线程池,c#,.net,multithreading,threadpool,C#,.net,Multithreading,Threadpool,下面是我使用的代码。主线程等待线程池线程执行。我使用AutoResetEvent(WaitHandle),但我真的很惊讶我偏离了目标,因为代码的行为并不像预期的那样 我有两个同心for循环,其中Threadpool位于内部循环中,对于外部循环的每次迭代,应该处理所有内部循环值。使用AutoResetEvent WaitOne调用使主线程在内部循环外部等待,该静态变量在外部循环每次迭代时重置为内部循环的最大值,并在方法调用中使用联锁递减。线程池线程用于调用AutoResetEvent的集合。但是,

下面是我使用的代码。主线程等待线程池线程执行。我使用AutoResetEvent(WaitHandle),但我真的很惊讶我偏离了目标,因为代码的行为并不像预期的那样

我有两个同心for循环,其中Threadpool位于内部循环中,对于外部循环的每次迭代,应该处理所有内部循环值。使用AutoResetEvent WaitOne调用使主线程在内部循环外部等待,该静态变量在外部循环每次迭代时重置为内部循环的最大值,并在方法调用中使用联锁递减。线程池线程用于调用AutoResetEvent的集合。但是,即使我期望静态变量在每个内部循环后显示值0,它也不会。我的代码中存在什么问题?对于我来说,完成任务有哪些更好的选择?事实上,由于这些值的混合,主线程似乎并不真正在等待线程池线程

using System;
using System.Threading;

namespace TestThreads
{
class Program
{
    private static int threadingCounter = 0;
    private static readonly object lockThreads = new Object();
    private AutoResetEvent areSync = new AutoResetEvent(true);

    // <param name="args"></param>
    static void Main(string[] args)
    {
        Program myProgram = new Program();

        try
        {
            try
            {   
                for (int outer = 0; outer < 1000; outer++)
                {
                    threadingCounter = 500;
                    try
                    {
                        for (int inner = 0; inner < 500; inner++)
                        {
                            ThreadPool.QueueUserWorkItem(new
                                 WaitCallback(myProgram.ThreadCall), inner);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Exception :: " + ex.Message);
                    }
                    finally
                    {                            
                        myProgram.areSync.WaitOne();
                    }

                    if(threadingCounter != 0)
                        Console.WriteLine("In Loop1, Thread Counter :: " +
                            threadingCounter);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception :: " + ex.Message);
            }                
        }
        catch(Exception ex)
        {
            Console.WriteLine("Exception :: " + ex.Message);
        }
        finally
        {
            threadingCounter = 0;

            if (myProgram.areSync != null)
            {
                myProgram.areSync.Dispose();
                myProgram.areSync = null;
            }
        }
    }

    public void ThreadCall(object state)
    {
        try
        {
            int inner = (int)state;
            Thread.Sleep(1);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception :: " + ex.Message);
        }
        finally
        {
            Interlocked.Decrement(ref threadingCounter);
            if (threadingCounter <= 0)
                areSync.Set();
        }                
    }        
 }
}
使用系统;
使用系统线程;
命名空间测试线程
{
班级计划
{
私有静态int threadingCounter=0;
私有静态只读对象锁线程=新对象();
private AutoResetEvent areSync=新的AutoResetEvent(真);
// 
静态void Main(字符串[]参数)
{
程序myProgram=新程序();
尝试
{
尝试
{   
用于(int-outer=0;outer<1000;outer++)
{
螺纹计数器=500;
尝试
{
用于(int-inner=0;inner<500;inner++)
{
ThreadPool.QueueUserWorkItem(新
WaitCallback(myProgram.ThreadCall),内部;
}
}
捕获(例外情况除外)
{
Console.WriteLine(“异常::”+ex.Message);
}
最后
{                            
myProgram.areSync.WaitOne();
}
如果(螺纹计数器!=0)
WriteLine(“在循环1中,线程计数器:”+
螺纹计数器);
}
}
捕获(例外情况除外)
{
Console.WriteLine(“异常::”+ex.Message);
}                
}
捕获(例外情况除外)
{
Console.WriteLine(“异常::”+ex.Message);
}
最后
{
螺纹计数器=0;
if(myProgram.areSync!=null)
{
myProgram.areSync.Dispose();
myProgram.areSync=null;
}
}
}
公共void线程调用(对象状态)
{
尝试
{
int内部=(int)状态;
睡眠(1);
}
捕获(例外情况除外)
{
Console.WriteLine(“异常::”+ex.Message);
}
最后
{
联锁减量(参考螺纹计数器);

如果(threadingCounter您已初始化AutoResetEvent,初始状态为signaled(true),这将允许首次调用

myProgram.areSync.WaitOne();
继续而不阻塞,因此它将继续执行外部循环,并再次将执行排队到线程池,因此结果将是混乱的

将代码更新为

private AutoResetEvent areSync = new AutoResetEvent(false);

对于预期的结果。希望这有助于

我将使用类似的方法重构它。这假设您希望在内部循环的后台线程中执行某些操作,在继续下一个外部循环之前完成这些操作,避免混乱的异常处理,同时仍然捕获处理过程中发生的异常,以便您可以在内外循环的处理完成后处理这些异常

// track exceptions that occurred in loops
class ErrorInfo
{
    public Exception Error { get; set; }
    public int Outer { get; set; }
    public int Inner { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // something to store execeptions from inner thread loop
        var errors = new ConcurrentBag<ErrorInfo>();
        // no need to wrap a try around this simple loop
        // unless you want an exception to stop the loop
        for (int outer = 0; outer < 10; outer++)
        {
            var tasks = new Task[50];
            for (int inner = 0; inner < 50; inner++)
            {
                var outerLocal = outer;
                var innerLocal = inner;
                tasks[inner] = Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            Thread.Sleep(innerLocal);
                            if (innerLocal % 5 == 0)
                            {
                                throw new Exception("Test of " + innerLocal);
                            }
                        }
                        catch (Exception e)
                        {
                            errors.Add(new ErrorInfo
                            {
                                Error = e,
                                Inner = innerLocal,
                                Outer = outerLocal
                            });
                        }
                    });
            }
            Task.WaitAll(tasks);
        }
        Console.WriteLine("Error bag contains {0} errors.", errors.Count);
        Console.ReadLine();
    }
}
//跟踪循环中发生的异常
类错误信息
{
公共异常错误{get;set;}
公共int外部{get;set;}
公共int内部{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
//用来存储来自内部线程循环的异常的东西
var错误=新的ConcurrentBag();
//不需要围绕这个简单的循环进行尝试
//除非您希望异常停止循环
用于(int-outer=0;outer<10;outer++)
{
var任务=新任务[50];
用于(int-inner=0;inner<50;inner++)
{
var outerLocal=外部;
var innerLocal=内部;
tasks[内部]=Task.Factory.StartNew(()=>
{
尝试
{
线程睡眠(innerLocal);
如果(innerLocal%5==0)
{
抛出新异常(“测试”+innerLocal);
}
}
捕获(例外e)
{
错误。添加(新的错误信息)
{
误差=e,
内部=内部本地,
外部=外部局部
});
}
});
}
Task.WaitAll(任务);
}
WriteLine(“错误包包含{0}个错误。”,errors.Count);
Console.ReadLine();
}
}

您的异常处理非常糟糕。至少有一个bug是可见的,您没有正确使用Interlocated.Decrement。您必须使用它的返回值,并且在变量递减时不要直接使用它。使用CountDownEvent可以成功