Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/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中使用多线程进行批处理#_C#_Multithreading_Parallel Processing_Task Parallel Library_Parallel.foreach - Fatal编程技术网

C# 如何在C中使用多线程进行批处理#

C# 如何在C中使用多线程进行批处理#,c#,multithreading,parallel-processing,task-parallel-library,parallel.foreach,C#,Multithreading,Parallel Processing,Task Parallel Library,Parallel.foreach,我使用parallel foreach在阻塞集合中添加值,但是当阻塞集合有10个值时,我需要对其进行一些处理,然后再次清除该阻塞集合,然后再次开始向阻塞集合添加值 这里有两个问题 当我对它进行一些处理时,它会不断地向阻塞集合添加值,我可以在列表上设置一个锁,但当它到达锁时,该值仍然会增加 如果我设置的锁完全破坏了并行编程的使用,我希望在处理这10条消息之前,在该列表中添加该对象。我可以复制列表内容并再次清空列表。同样的问题,我只能复制10项,因为内容已经更改 有时,if条件永远不会满足,因为

我使用parallel foreach在阻塞集合中添加值,但是当阻塞集合有10个值时,我需要对其进行一些处理,然后再次清除该阻塞集合,然后再次开始向阻塞集合添加值

这里有两个问题

  • 当我对它进行一些处理时,它会不断地向阻塞集合添加值,我可以在列表上设置一个锁,但当它到达锁时,该值仍然会增加

  • 如果我设置的锁完全破坏了并行编程的使用,我希望在处理这10条消息之前,在该列表中添加该对象。我可以复制列表内容并再次清空列表。同样的问题,我只能复制10项,因为内容已经更改

  • 有时,if条件永远不会满足,因为在检查条件之前,值会增加

    有什么解决办法吗

    public static BlockingCollection<string> failedMessages = new BlockingCollection<string>();
    static void Main(string[] args)
    {
        var myCollection = new List<string>();
        myCollection.Add("test");
        //Consider myCollection having more than 100 items 
        Parallel.ForEach(myCollection, item =>
        {
            failedMessages.Add(item);
            if (failedMessages.Count == 10)
            {
                DoSomething();
            }
        });
    
    }
    
    static public void DoSomething()
    {
        //dosome operation with failedMessages 
        failedMessages = new BlockingCollection<string>();
    }   
    
        
    
    public static BlockingCollection failedMessages=new BlockingCollection();
    静态void Main(字符串[]参数)
    {
    var myCollection=新列表();
    myCollection.添加(“测试”);
    //考虑myCollection有100多个项目
    Parallel.ForEach(myCollection,item=>
    {
    失败消息。添加(项);
    如果(failedMessages.Count==10)
    {
    DoSomething();
    }
    });
    }
    静态公共空间剂量测量()
    {
    //dosome操作与失败消息
    failedMessages=新建BlockingCollection();
    }   
    
    这看起来像是数据流的作业:

    使用batchsize为10的
    BatchBlock
    ActionBlock
    消耗批次的示例:

    using System;
    using System.Threading.Tasks;
    using System.Threading.Tasks.Dataflow;
                        
    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("Hello World");
            // Set up DataFlow Blocks
            BatchBlock<string> batcher = new BatchBlock<string>( 10 );
            ActionBlock<string[]> consumer = 
                new ActionBlock<string[]>( 
                    (msgs) => Console.WriteLine("Processed {0} messages.", msgs.Length)
                );
            // put them together
            batcher.LinkTo( consumer );
            
            // start posting
            Parallel.For( 0, 103, (i) => batcher.Post(string.Format("Test {0}",i)));
            
            // shutdown
            batcher.Complete();
            batcher.Completion.Wait();
        }
    }
    
    使用系统;
    使用System.Threading.Tasks;
    使用System.Threading.Tasks.Dataflow;
    公共课程
    {
    公共静态void Main()
    {
    Console.WriteLine(“你好世界”);
    //设置数据流块
    批块配料器=新批块(10);
    ActionBlock使用者=
    新动作块(
    (msgs)=>Console.WriteLine(“已处理的{0}条消息。”,msgs.Length)
    );
    //把它们放在一起
    batcher.LinkTo(消费者);
    //开始发帖
    Parallel.For(0103,(i)=>batcher.Post(string.Format(“Test{0}”,i));
    //关闭
    batcher.Complete();
    batcher.Completion.Wait();
    }
    }
    
    在行动中:

    进一步阅读:


    编辑:根据要求-如果您不能或不想使用数据流,您当然可以执行类似的操作:

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using System.Collections.Concurrent;
    using System.Linq;
                        
    public class Program
    {
        public static void Main()
        {
            FailedMessageHandler fmh = new FailedMessageHandler( new Progress<string[]>((list) => { Console.WriteLine("Handling {0} messages. [{1}]", list.Length, string.Join(",", list));}));
            Parallel.For(0,52, (i) => {fmh.Add(string.Format("Test {0,3}",i));});
            Thread.Sleep(1500); // Demo: Timeout
            var result = Parallel.For(53,107, (i) => {fmh.Add(string.Format("Test {0,3}",i));});
            while(!result.IsCompleted)
            {
                // Let Parallel.For run to end ...
                Thread.Sleep(10);
            }
            // Graceful shutdown:
            fmh.CompleteAdding();
            fmh.AwaitCompletion();
        }
    }
    
    public class FailedMessageHandler
    {
        private BlockingCollection<string> workQueue = new BlockingCollection<string>();
        private List<string> currentBuffer = new List<string>(10);
        private IProgress<string[]> progress;
        private Thread workThread;
        
        public FailedMessageHandler( IProgress<string[]> progress )
        {
            this.progress = progress;
            workThread = new Thread(WatchDog);
            workThread.Start();
        }
        
        public void Add( string failedMessage )
        {
            if ( workQueue.IsAddingCompleted )
            {
                throw new InvalidOperationException("Adding is completed!");
            }
            
            workQueue.Add(failedMessage);
        }
        
        private void WatchDog()
        {
            while(true)
            {
                // Demo: Include a timeout - If there are less than 10 items
                // for x amount of time, send whatever you got so far.
                CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(1));
                try{
                   var failedMsg = workQueue.Take(timeout.Token);
                   currentBuffer.Add(failedMsg);
                   if( currentBuffer.Count >= 10 ){
                       progress.Report(currentBuffer.ToArray());
                       currentBuffer.Clear();
                   }
                }
                catch(OperationCanceledException)
                {
                    Console.WriteLine("TIMEOUT!");
                    // timeout.
                    if( currentBuffer.Any() ) // handle items if there are
                    {
                        progress.Report(currentBuffer.ToArray());
                        currentBuffer.Clear();
                    }
                }
                catch(InvalidOperationException)
                {
                    Console.WriteLine("COMPLETED!");
                    // queue has been completed.
                    if( currentBuffer.Any() ) // handle remaining items
                    {
                        progress.Report(currentBuffer.ToArray());
                        currentBuffer.Clear();
                    }
                    break;
                }
            }
            Console.WriteLine("DONE!");
        }
        
        public void CompleteAdding()
        {
            workQueue.CompleteAdding();
        }
        
        public void AwaitCompletion()
        {
            if( workThread != null )
                workThread.Join();
        }
    }
    
    使用系统;
    使用系统线程;
    使用System.Threading.Tasks;
    使用System.Collections.Generic;
    使用System.Collections.Concurrent;
    使用System.Linq;
    公共课程
    {
    公共静态void Main()
    {
    FailedMessageHandler fmh=新的FailedMessageHandler(新进度((列表)=>{Console.WriteLine(“处理{0}条消息。[{1}]”,列表.Length,string.Join(“,”,列表));});
    对于(0,52,(i)=>{fmh.Add(string.Format(“Test{0,3}”,i));});
    Thread.Sleep(1500);//演示:超时
    var result=Parallel.For(53107,(i)=>{fmh.Add(string.Format(“Test{0,3}”,i));});
    而(!result.IsCompleted)
    {
    //让我们平行。为了跑完。。。
    睡眠(10);
    }
    //正常关机:
    fmh.CompleteAdding();
    fmh.等待完成();
    }
    }
    公共类FailedMessageHandler
    {
    private BlockingCollection workQueue=new BlockingCollection();
    私有列表currentBuffer=新列表(10);
    私营部门的进步;
    私有线程工作线程;
    public FailedMessageHandler(IProgress进程)
    {
    这个。进步=进步;
    工作线程=新线程(看门狗);
    workThread.Start();
    }
    公共无效添加(字符串失败消息)
    {
    if(workQueue.IsAddingCompleted)
    {
    抛出新的InvalidOperationException(“添加已完成!”);
    }
    添加(失败消息);
    }
    私人监察机构
    {
    while(true)
    {
    //演示:包括超时-如果少于10项
    //在x时间内,发送到目前为止得到的任何信息。
    CancellationTokenSource超时=新的CancellationTokenSource(TimeSpan.FromSeconds(1));
    试一试{
    var failedMsg=workQueue.Take(timeout.Token);
    currentBuffer.Add(failedMsg);
    如果(currentBuffer.Count>=10){
    progress.Report(currentBuffer.ToArray());
    currentBuffer.Clear();
    }
    }
    捕获(操作取消异常)
    {
    控制台。WriteLine(“超时!”);
    //超时。
    if(currentBuffer.Any())//如果存在
    {
    progress.Report(currentBuffer.ToArray());
    currentBuffer.Clear();
    }
    }
    捕获(无效操作异常)
    {
    Console.WriteLine(“已完成!”);
    //队列已完成。
    if(currentBuffer.Any())//处理剩余项
    {
    progress.Report(currentBuffer.ToArray());
    currentBuffer.Clear();
    }
    打破
    }
    }
    控制台。WriteLine(“完成!”);
    }
    公共无效完成添加()
    {
    workQueue.CompleteAdding();
    }
    公众假期待完成()
    {
    if(工作线程!=null)
    workThread.Join();
    }
    }
    
    在行动中:

    请注意,使用
    Progress
    将在主线程上执行处理。如果您传递一个
    A