我试图使用Chunkify方法来“捕获”所有“待定”项目。 但我发现了一个问题,消耗了一个线程的所有资源,有谁知道为什么会发生这种情况,我该如何防止这种情况?
事实上,我的目标是为我的活动创建一个“垃圾邮件过滤器”,仅选择最后5个值,并忽略连续两次以上的重复。
问题发生的一个例子:
注意!以下代码是愚蠢而毫无意义的。它只是为了演示问题,并指出该事件可以被称为多个线程 (请运行上面的代码并观察输出窗口,这是问题所在。)
[TestMethod]
public void ThreadSpinning()
{
var subs = Observable.FromEventPattern(add => this.Raise += add, rem => this.Raise -= rem)
.Select((item, countRaise) => countRaise)
.Chunkify()
.ToObservable(Scheduler.Default)
.Select((countRaise, countChunkify) => new { raiseItems = countRaise, countChunkify })
.Do(obj => Trace.Write("Chunkify = " + obj.countChunkify + " | "))
.Select(a => a.raiseItems)
.Where(a => a.Any())
.Do(obj =>
{
Trace.WriteLine("[ Start do something.. Raise = " + Dump(obj) + " ] " +
Environment.NewLine + Environment.NewLine);
Thread.Sleep(700);
}).Subscribe();
Thread.Sleep(2000);
var handle = new ManualResetEventSlim(false);
ThreadPool.QueueUserWorkItem(r =>
{
Thread.Sleep(500);
Task.Factory.StartNew(() =>
{
OnRaise();
OnRaise();
}).Wait();
OnRaise();
Thread.Sleep(500);
OnRaise();
Task.Factory.StartNew(OnRaise).Wait();
Thread.Sleep(1500);
OnRaise();
OnRaise();
Thread.Sleep(500);
OnRaise();
Thread.Sleep(250);
OnRaise();
Task.Factory.StartNew(OnRaise).Wait();
Thread.Sleep(500);
Task.Factory.StartNew(OnRaise).Wait();
Task.Factory.StartNew(OnRaise).Wait();
Thread.Sleep(2000);
handle.Set();
});
handle.Wait();
Thread.Sleep(3000);
subs.Dispose();
Thread.Sleep(1000);
}
private event EventHandler Raise;
protected virtual void OnRaise()
{
EventHandler handler = Raise;
if (handler != null)
handler(this, EventArgs.Empty);
}
public static string Dump<T>(IEnumerable<T> source)
{
return source.Select(a => a.ToString()).Aggregate((a, b) => a + ", " + b);
}
答案 0 :(得分:1)
我不确定您要做什么,但您的代码存在一些问题:
您正在使用Chunkify
从IObservable
转换为IEnumerable
,但之后又将其转换为IObservable
,这有点奇怪。
陈述
.Select((item, count) => new { item, count })
.Do(obj => Trace.Write(obj.count + " | "))
.Select(a => a.item)
.Where(a => a.Any())
.Do(obj => Trace.WriteLine("Do something.. " + obj.Dump()))
很多代码似乎只是为了调试而进行转换。您可以在一个Do
调用中的一个语句lambda中编写所有调试代码。
您不应该创建新的Random
个对象,而是重用一个并在其上调用Next()
:http://msdn.microsoft.com/en-us/library/h343ddh9.aspx
您过度使用Thread.Sleep
,并且在可观察的序列中执行此操作会产生代码异味。尝试将代码转换为使用各种时间运算符,例如Throttle
和Delay
。您可能还想使用Observable.Generate
创建序列。
Chunkify
可能实际上与您无关 - 您是否考虑过Buffer
运营商?这里有一个很好的时间运算符列表:http://introtorx.com/Content/v1.0.10621.0/13_TimeShiftedSequences.html#TimeShiftedSequences
要测试代码,您不需要实际引发事件处理程序,只需通过生成可观察序列并订阅它来测试您的订阅代码。例如,如果您有一个方法SubscribeToMyEvent(IObservable<T>)
,那么您可以通过传递使用FromEventPattern
创建的可观察量或使用Interval
或Generate
创建的方法来设置它。
你的情景究竟是什么?什么是触发事件?你究竟想要改变你的事件流?绘制大理石图(例如http://channel9.msdn.com/blogs/j.van.gogh/reactive-extensions-api-in-depth-marble-diagrams-select--where)以便考虑您的算法会很有帮助。