C# 具有流大小而不是流数量的缓冲区# 我有一个Producer() 在Consumer()中,我使用System.Reactive(4.1.2)订阅了阻塞集合作为可观察 我使用的是缓冲区,但只能缓冲大量的流
问题-我可以使用C# 具有流大小而不是流数量的缓冲区# 我有一个Producer() 在Consumer()中,我使用System.Reactive(4.1.2)订阅了阻塞集合作为可观察 我使用的是缓冲区,但只能缓冲大量的流,c#,system.reactive,C#,System.reactive,问题-我可以使用buffer运算符处理流的大小而不是流的数量吗 当缓冲区大小交叉时(例如1024KB或1MB),创建新的缓冲区? class Program { private static readonly BlockingCollection<Message> MessagesBlockingCollection = new BlockingCollection<Message>(); private static void
buffer
运算符处理流的大小而不是流的数量吗
当缓冲区大小交叉时(例如1024KB或1MB),创建新的缓冲区?
class Program
{
private static readonly BlockingCollection<Message> MessagesBlockingCollection = new BlockingCollection<Message>();
private static void Producer()
{
int ctr = 1;
while (ctr <= 11)
{
MessagesBlockingCollection.Add(new Message { Id = ctr, Name = $"Name-{ctr}" });
Thread.Sleep(1000);
ctr++;
}
}
private static void Consumer()
{
var observable = MessagesBlockingCollection.GetConsumingEnumerable().ToObservable();
var bufferedNumberStream = observable.BufferWithThrottle(TimeSpan.FromSeconds(60), 5)
.Subscribe(ts =>
{
WriteToFile(ts.ToList());
});
}
private static void WriteToFile(List<Message> listToWrite)
{
using (StreamWriter outFile = System.IO.File.CreateText(Path.Combine(@"C:\TEMP", $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.json")))
{
outFile.Write(JsonConvert.SerializeObject(listToWrite));
}
}
static void Main(string[] args)
{
var producer = Task.Factory.StartNew(() => Producer());
var consumer = Task.Factory.StartNew(() => Consumer());
Console.Read();
}
}
类程序
{
私有静态只读BlockingCollection消息BlockingCollection=新建BlockingCollection();
私有静态无效生成器()
{
int ctr=1;
while(ctr)
{
WriteToFile(ts.ToList());
});
}
私有静态无效写入文件(列表列表写入)
{
使用(StreamWriter outFile=System.IO.File.CreateText(Path.Combine(@“C:\TEMP”,$”{DateTime.Now.ToString(“yyyymmddhhmmssff”)}.json”))
{
Write(JsonConvert.SerializeObject(listToWrite));
}
}
静态void Main(字符串[]参数)
{
var producer=Task.Factory.StartNew(()=>producer());
var consumer=Task.Factory.StartNew(()=>consumer());
Console.Read();
}
}
可观测延拓法
public static IObservable<IList<TSource>> BufferWithThrottle<TSource>(this IObservable<TSource> source,
TimeSpan threshold, int noOfStream)
{
return Observable.Create<IList<TSource>>((obs) =>
{
return source.GroupByUntil(_ => true,
g => g.Throttle(threshold).Select(_ => Unit.Default)
.Merge(g.Buffer(noOfStream).Select(_ => Unit.Default)))
.SelectMany(i => i.ToList())
.Subscribe(obs);
});
}
public static IObservable BufferWithThrottle(此IObservable源,
时间跨度阈值,int noOfStream)
{
返回可观察。创建((obs)=>
{
返回source.GroupByUntil(=>true,
g=>g.Throttle(阈值)。选择(=>Unit.Default)
.Merge(g.Buffer(noOfStream).Select(=>Unit.Default)))
.SelectMany(i=>i.ToList())
.认购(obs);
});
}
很高兴看到扩展方法在使用:)
您可以稍微修改它,使其扫描消息的运行计数
大小。这样我们就失去了类型泛型
public class Message
{
public string Payload { get; set; }
public int Size { get; set; }
}
public static IObservable<IList<Message>> BufferWithThrottle(this IObservable<Message> source,
TimeSpan threshold, int maxSize)
{
return Observable.Create<IList<Message>>((obs) =>
{
return source.GroupByUntil(_ => true,
g => g.Throttle(threshold).Select(_ => Unit.Default)
.Merge(g.Select( i => i.Size)
.Scan(0, (a, b) => a + b)
.Where(a => a >= maxSize)
.Select(_ => Unit.Default)))
.SelectMany(i => i.ToList())
.Subscribe(obs);
});
}
公共类消息
{
公共字符串有效负载{get;set;}
公共整数大小{get;set;}
}
公共静态IObservable BufferWithThrottle(此IObservable源,
时间跨度阈值,int maxSize)
{
返回可观察。创建((obs)=>
{
返回source.GroupByUntil(=>true,
g=>g.Throttle(阈值)。选择(=>Unit.Default)
.Merge(g.Select(i=>i.Size)
.扫描(0,(a,b)=>a+b)
。其中(a=>a>=maxSize)
.Select(=>Unit.Default)))
.SelectMany(i=>i.ToList())
.认购(obs);
});
}
谢谢:),但是如何计算消息大小呢?我又写了一个类'BatchMessage,我在计算消息大小,
公共类BatchMessage{public message message{get;set;}public int Size{get;set;}public BatchMessage(message message){this.Message=Message;var msg=Newtonsoft.Json.JsonConvert.SerializeObject(Message);this.Size=msg.Length+1;}}}}`然后使用扩展名IObservable
Yep,这大致就是获得Json字符串大小(或字符长度)的方式。虽然它与写入磁盘的文件保留的字节数不同。@Enigmativity,请重新打开此问题,我将删除另一个问题。谢谢!