/Collections/Specialized/ObservableConcurrentQueue.cs |
@@ -1,14 +1,12 @@ |
// -------------------------------------------------------------------------------------------------------------------- |
// <copyright file="ObservableConcurrentQueue.cs" company="BledSoft"> |
// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. |
// To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/. |
// </copyright> |
// <Author> |
// Cheikh Younes |
// </Author> |
// -------------------------------------------------------------------------------------------------------------------- |
using System; |
using System.Threading; |
using System.Threading.Tasks; |
using System.Collections.ObjectModel; |
using System.Collections.Concurrent; |
using System.Threading.Tasks; |
using System.Collections; |
using System.Collections.Generic; |
using System.Collections.Specialized; |
using System.Linq; |
|
namespace wasSharp.Collections.Specialized |
{ |
@@ -18,114 +16,71 @@ |
/// <typeparam name="T"> |
/// The content type |
/// </typeparam> |
public sealed class ObservableConcurrentQueue<T> : ConcurrentQueue<T> |
public sealed class ObservableConcurrentQueue<T> : ConcurrentQueue<T>, INotifyCollectionChanged |
{ |
#region Public Events |
public event NotifyCollectionChangedEventHandler CollectionChanged; |
|
/// <summary> |
/// Occurs when concurrent queue elements [changed]. |
/// </summary> |
public event ConcurrentQueueChangedEventHandler<T> ContentChanged; |
private new void Enqueue(T item) |
{ |
EnqueueAsync(item).RunSynchronously(); |
} |
|
#endregion |
|
#region Public Methods and Operators |
|
/// <summary> |
/// Adds an object to the end of the <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/>. |
/// </summary> |
/// <param name="item"> |
/// The object to add to the end of the <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/> |
/// . The value can be a null reference (Nothing in Visual Basic) for reference types. |
/// </param> |
public new async Task Enqueue(T item) |
public async Task EnqueueAsync(T item) => await Task.Run(() => |
{ |
await new Task(() => |
{ |
base.Enqueue(item); |
|
// Raise event added event |
this.OnContentChanged( |
new NotifyConcurrentQueueChangedEventArgs<T>(NotifyConcurrentQueueChangedAction.Enqueue, item)); |
OnCollectionChanged( |
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); |
}); |
} |
|
/// <summary> |
/// Attempts to remove and return the object at the beginning of the |
/// <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/>. |
/// </summary> |
/// <param name="result"> |
/// When this method returns, if the operation was successful, <paramref name="result"/> contains the |
/// object removed. If no object was available to be removed, the value is unspecified. |
/// </param> |
/// <returns> |
/// true if an element was removed and returned from the beginning of the |
/// <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/> successfully; otherwise, false. |
/// </returns> |
public new bool TryDequeue(out T result) |
private new bool TryDequeue(out T result) |
{ |
if (!base.TryDequeue(out result)) |
{ |
result = DequeueAsync().Result; |
if (result.Equals(default(T))) |
return false; |
|
return true; |
} |
|
// Raise item dequeued event |
this.OnContentChanged( |
new NotifyConcurrentQueueChangedEventArgs<T>(NotifyConcurrentQueueChangedAction.Dequeue, result)); |
public async Task<T> DequeueAsync() => await Task.Run(() => |
{ |
if (!base.TryDequeue(out T item)) |
return default(T); |
|
if (this.IsEmpty) |
OnCollectionChanged( |
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); |
|
return item; |
}); |
|
public async Task<T> PeekAsync() => await Task.Run(() => |
{ |
// Raise Queue empty event |
this.OnContentChanged( |
new NotifyConcurrentQueueChangedEventArgs<T>(NotifyConcurrentQueueChangedAction.Empty)); |
} |
if (!base.TryPeek(out T item)) |
return default(T); |
|
return item; |
}); |
|
private new bool TryPeek(out T result) |
{ |
result = PeekAsync().Result; |
|
if (result.Equals(default(T))) |
return false; |
|
return true; |
} |
|
/// <summary> |
/// Attempts to return an object from the beginning of the |
/// <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/> without removing it. |
/// </summary> |
/// <param name="result"> |
/// When this method returns, <paramref name="result"/> contains an object from the beginning of the |
/// <see cref="T:System.Collections.Concurrent.ConcurrentQueue`1"/> or an unspecified value if the operation failed. |
/// </param> |
/// <returns> |
/// true if and object was returned successfully; otherwise, false. |
/// </returns> |
public new bool TryPeek(out T result) |
private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) |
{ |
var retValue = base.TryPeek(out result); |
if (retValue) |
{ |
// Raise item dequeued event |
this.OnContentChanged( |
new NotifyConcurrentQueueChangedEventArgs<T>(NotifyConcurrentQueueChangedAction.Peek, result)); |
CollectionChanged?.Invoke(this, args); |
} |
|
return retValue; |
} |
|
#endregion |
|
#region Methods |
|
/// <summary> |
/// Raises the <see cref="E:Changed"/> event. |
/// </summary> |
/// <param name="args"> |
/// The <see cref="NotifyConcurrentQueueChangedEventArgs{T}"/> instance containing the event data. |
/// </param> |
private void OnContentChanged(NotifyConcurrentQueueChangedEventArgs<T> args) |
public async Task Clear() |
{ |
var handler = this.ContentChanged; |
if (handler != null) |
{ |
handler(this, args); |
while (!base.IsEmpty) |
await DequeueAsync(); |
} |
} |
|
#endregion |
} |
} |