Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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# 每个竞争条件的并行性_C#_Parallel.foreach - Fatal编程技术网

C# 每个竞争条件的并行性

C# 每个竞争条件的并行性,c#,parallel.foreach,C#,Parallel.foreach,在parallel.ForEach循环中,我周期性地进入我认为是竞争条件的状态。我这样说是因为它总是挂在代码的这一部分上 try { Parallel.ForEach(Directory.EnumerateFiles(directory, "*.tracex", SearchOption.TopDirectoryOnly), _po, (path, ls) => { DebugFile file; if (filter

在parallel.ForEach循环中,我周期性地进入我认为是竞争条件的状态。我这样说是因为它总是挂在代码的这一部分上

try
{
    Parallel.ForEach(Directory.EnumerateFiles(directory, "*.tracex", SearchOption.TopDirectoryOnly), _po, (path, ls) =>
        {
            DebugFile file;
            if (filterDate)
            {
                if (filterUser)
                {
                    file = new DebugFile(path, startTime, endTime, user);
                }
                else file = new DebugFile(path, startTime, endTime);
            }
            else if (filterUser)
            {
                file = new DebugFile(path, user);
            }
            else file = new DebugFile(path);
            if (!file.IsFiltered()) 
            {
                _files.Add(file);
            }
            Interlocked.Increment(ref _loadCount);  // increment how many we've checked
            if (_po.CancellationToken.IsCancellationRequested)
            {
                ls.Break();
            }
        });
}
catch (OperationCanceledException oce)
{
    Debug.WriteLine(oce.ToString());
}
在my_files对象中,我在调用Add方法时处理锁定

public virtual void Add(T item)
{
    _lock.EnterWriteLock();
    try
    {
        _bindingList.Add(item);
    }
    finally
    {
        _lock.ExitWriteLock();
    }
    OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, _bindingList.Count - 1));
}
知道我做错了什么吗?它不是每次都挂,只是偶尔挂。而且,至少对我来说,它不会在我第一次调用代码时发生。只有当我调用它一次,然后再调用它时才会发生,通常是第二次或第三次

谢谢

更新 我意识到我正在使用一个定制的任务调度器。当我移除它时,我再也看不到挂起。我这样做是为了可以自定义运行的线程数。我的想法是,由于我主要是通过网络读取文件,IO会减慢速度,这样我就可以一次运行更多任务。下面是我如何构建调度器的:

public class TaskSchedulerForSlowIO : TaskScheduler
{
    /// <summary>
    /// maximum number of tasks to run concurrently
    /// </summary>
    private int _maxConcurrencyLevel;

    /// <summary>
    /// lock for reading tasks array
    /// </summary>
    private ReaderWriterLockSlim _listLock = new ReaderWriterLockSlim();

    /// <summary>
    /// list of tasks running
    /// </summary>
    private LinkedList<Task> _tasks = new LinkedList<Task>();

    /// <summary>
    /// Default constructor - This will increase threadpool limits if necessary
    /// </summary>
    public TaskSchedulerForSlowIO()
        : base()
    {
        _maxConcurrencyLevel = Environment.ProcessorCount * 10;
        int workerThreads, ioThreads, minimumConcurrency;
        minimumConcurrency = Environment.ProcessorCount * 2;
        ThreadPool.GetMaxThreads(out workerThreads, out ioThreads);
        if (workerThreads < _maxConcurrencyLevel)
        {
            if (ioThreads < _maxConcurrencyLevel)
            {
                ioThreads = _maxConcurrencyLevel;
            }
            ThreadPool.SetMaxThreads(_maxConcurrencyLevel, ioThreads);
        }
        ThreadPool.GetMinThreads(out workerThreads, out ioThreads);
        if (workerThreads < minimumConcurrency)
        {
            if (ioThreads < minimumConcurrency)
            {
                ioThreads = minimumConcurrency;
            }
            ThreadPool.SetMinThreads(minimumConcurrency, ioThreads);
        }
    }

    /// <summary>
    /// Implementing TaskScheduler
    /// </summary>
    public override int MaximumConcurrencyLevel
    {
        get
        {
            return _maxConcurrencyLevel;
        }
    }

    /// <summary>
    /// Scheduler Implementation
    /// </summary>
    /// <returns>ScheduledTasks</returns>
    protected override IEnumerable<Task> GetScheduledTasks()
    {
        Task[] tasks;
        _listLock.EnterReadLock();
        try
        {
            tasks = _tasks.ToArray();
        }
        finally
        {
            _listLock.ExitReadLock();
        }
        return tasks;
    }

    /// <summary>
    /// Queues the specified task
    /// </summary>
    /// <param name="task">Task to queue</param>
    protected override void QueueTask(Task task)
    {
        int count;
        _listLock.EnterReadLock();
        try
        {
            _tasks.AddLast(task);
            count = _tasks.Count;
        }
        finally
        {
            _listLock.ExitReadLock();
        }
        if (count <= _maxConcurrencyLevel)
        {
            ThreadPool.UnsafeQueueUserWorkItem(ProcessTask, task);
        }
    }

    /// <summary>
    /// Scheduler Implementation
    /// </summary>
    /// <param name="task">Task to remove</param>
    /// <returns>Success</returns>
    protected override bool TryDequeue(Task task)
    {
        _listLock.EnterWriteLock();
        try
        {
            return _tasks.Remove(task);
        }
        finally
        {
            _listLock.ExitWriteLock();
        }
    }

    /// <summary>
    /// Scheduled Implementation
    /// </summary>
    /// <param name="task">Task to execute</param>
    /// <param name="taskWasPreviouslyQueued">Was the task previously queued</param>
    /// <returns></returns>
    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
        //We're not going to inline slow IO
        return false;
    }

    void ProcessTask(object o)
    {
        try
        {
            Task t = o as Task;
            if (t != null)
            {
                if (base.TryExecuteTask(t))
                {
                    if(!(t.IsCanceled || t.IsFaulted)) t.Wait();
                    TryDequeue(t);
                }
            }
        }
        catch(AggregateException a)
        {
            var e = a.Flatten();
            foreach (Exception ex in e.InnerExceptions)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
    }
}
公共类TaskSchedulerForSlowIO:TaskScheduler
{
/// 
///要同时运行的最大任务数
/// 
私有int_最大并发级别;
/// 
///读取任务数组的锁
/// 
私有ReaderWriterLockSlim _listLock=new ReaderWriterLockSlim();
/// 
///正在运行的任务列表
/// 
私有LinkedList_tasks=新建LinkedList();
/// 
///默认构造函数-这将在必要时增加线程池限制
/// 
公共任务调度程序forslowio()
:base()
{
_maxConcurrencyLevel=Environment.ProcessorCount*10;
int workerThreads、ioThreads、minimumConcurrency;
minimumConcurrency=Environment.ProcessorCount*2;
GetMaxThreads(out-workerThreads,out-ioThreads);
if(workerThreads<_maxConcurrencyLevel)
{
如果(ioThreads<_maxConcurrencyLevel)
{
ioThreads=\u最大并发级别;
}
SetMaxThreads(_maxConcurrencyLevel,ioThreads);
}
GetMinThreads(out-workerThreads,out-ioThreads);
if(workerThreads<最小并发)
{
if(ioThreads如果(count),可能有很多原因。
比如说

1) 从代码上看,
filterUser
filterDate
IsFiltered()
…的起源以及突变特征不清楚,这可能会导致问题

2) 一般来说,代码是不可伸缩的。避免并行访问(读取)文件,因为IO设备(我想在您的情况下是硬盘)不是并行读取设备,并且您很可能会在简单串行处理的情况下获得更差的性能


建议:将线程亲和力设置为仅2个线程/核心(我再次假定您有更多),然后调试,看看会发生什么。最有可能的情况是,您会遇到冲突。

我首先要摆脱
Add
方法中的
try
/finally
。捕获所有异常处理会使调试变得非常困难。这样做,然后看看是否会抛出任何东西。@Enigmativity
try/finally
不会mean Catch all exception只是为了确保执行了
\u lock.ExitWriteLock();
。griztown,当您将方法替换为
lock(aSharedObj)\u bindingList.Add(item);
?什么是
\u files
?类型的对象具有
Add()
您显示的方法?您应该注意,如果您正在写入对象,则需要保护对该对象的所有访问;例如,
\u bindingList.Count
不是线程安全的,并且必须位于
锁内。由于缺少完整的代码示例,您可能还存在其他线程错误。如果您需要具体答案。_files是我创建的一个类,它是一个可排序的绑定列表。因此,_files对象的基础_bindinglist属性。因此,听起来我需要在parallel.ForEach循环中执行任何操作之前锁定_文件?您的帖子并不是问题的答案。建议:不要尝试回答无法回答的问题。谢谢s Tigran.filterUser和filterDate是布尔值,它们告诉我们是否要根据关联的用户或创建文件的日期/时间筛选文件。IsFiltered是DebugFile类上的一个标志,用于设置是否应筛选文件。我将测试其他建议。我将线程设置为8(我有4个核)现在它每次都挂起。但我还是不明白为什么。你知道谁来调试这个吗?我找到了问题的根源,一个自定义任务调度程序。我在上面添加了代码。如果有什么问题,请告诉我。为什么要编写
\u maxConcurrencyLevel=Environment.ProcessorCount*10;
?你希望每个核心运行10个线程吗?