我需要在达到Collection容量或发生超时时执行某些操作。
例如,如果我有一个容量为10的列表,超时为10秒则必须等待其中一个"事件"提出要执行某事。
我正在考虑使用 ObservableCollection ,并且在事件 CollectionChanged()中计算集合的项目数,并查看是否等于请求的最大数量允许。
同时我将有一个计时器来控制超时。
有人可以告诉我是否有更好的解决方案?
提前多多感谢。
答案 0 :(得分:1)
您可以使用所需功能实现自己的收藏。 像这样:
static void Main()
{
var list = new MyObservableCollection<int>(10, 10);
list.ConditionReachedEvent += () =>
{
//Do something
};
list.StartTimer();
Task.Factory.StartNew(
() =>
{
// Simulate slow operation
Thread.Sleep(12000);
for (var i = 0; i < 10; i++)
{
list.Add(i);
}
});
Console.Read();
}
public sealed class MyObservableCollection<T> : System.Collections.ObjectModel.ObservableCollection<T>
{
public event Action ConditionReachedEvent = delegate { };
private System.Threading.Timer timer;
private readonly int alertThreshold;
private long isEventRaised = 0;
private readonly int timeout = 0;
public MyObservableCollection(int alertThreshold, int timeout)
{
this.alertThreshold = alertThreshold;
this.timeout = timeout * 1000;
}
public void StartTimer()
{
Interlocked.Exchange(ref this.isEventRaised, 0);
this.StopTimer();
this.timer = new Timer(x =>
{
this.RaiseEvent();
}, null, this.timeout, this.timeout);
}
private void StopTimer()
{
if (this.timer != null)
{
this.timer.Dispose();
this.timer = null;
}
}
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if (this.Count >= this.alertThreshold)
{
this.RaiseEvent();
}
}
private void RaiseEvent()
{
this.StopTimer();
if (Interlocked.CompareExchange(ref this.isEventRaised, 1, 0) != 0)
{
return;
}
this.ConditionReachedEvent();
}
}
使用async / await
static void Main()
{
var list = new MyObservableCollection<int>(10);
list.ConditionReachedEvent += () =>
{
};
list.Start(10);
Task.Run(
() =>
{
// Simulate slow operation
Thread.Sleep(TimeSpan.FromSeconds(12));
for (var i = 0; i < 10; i++)
{
list.Add(i);
}
});
Console.Read();
}
public sealed class MyObservableCollection<T> : System.Collections.ObjectModel.ObservableCollection<T>
{
public event Action ConditionReachedEvent = delegate { };
private readonly int alertThreshold;
private readonly TaskCompletionSource<object> capacityReached = new TaskCompletionSource<object>();
public MyObservableCollection(int alertThreshold)
{
this.alertThreshold = alertThreshold;
}
public async void Start(int timeout)
{
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeout));
var capacityReachedTask = capacityReached.Task;
await Task.WhenAny(capacityReachedTask, timeoutTask);
this.ConditionReachedEvent();
}
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if (this.Count >= this.alertThreshold)
{
capacityReached.TrySetResult(null);
}
}
}
答案 1 :(得分:0)
如果我这样做,我会使用Microsoft的Reactive Framework(NuGet&#34; Rx-Main&#34;)。然后你可以这样做:
var collection = new ObservableCollection<int>();
var query =
Observable
.FromEventPattern<
NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
h => collection.CollectionChanged += h, h => collection.CollectionChanged -= h)
.Select(ep => collection.Count == 10)
.Where(x => x)
.Take(1)
.Timeout(TimeSpan.FromSeconds(10.0), Observable.Return(false));
query.Subscribe(flag =>
{
if (flag) // capacity
{
}
else //timeout
{
}
});
因此query
有效地监视CollectionChanged
事件并计算计数是否等于10,仅当它为10时返回(并返回true
),并取一个值。然后它会施加超时,在10.0秒后返回false
。