C# 如何在C中使用多线程进行批处理#
我使用parallel foreach在阻塞集合中添加值,但是当阻塞集合有10个值时,我需要对其进行一些处理,然后再次清除该阻塞集合,然后再次开始向阻塞集合添加值 这里有两个问题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条件永远不会满足,因为
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