How to visualize a blockingcollection - c#

I think i have some problems with logic right now.
I have used a blocking collection to make thread safe calls to other PCs. In general it looks like this:
public class MyClass
{
private BlockingCollection<workUnit> workUnits = new BlockingCollection<workUnit>();
public void EnQueue(workUnit item)
{
workUnits.Add(item);
}
private void DeQueue()
{
while (!stopFlag)
{
workUnit item = workUnits.Take();
DoLongRunningDBStuff(workUnit);
}
}
}
Now I want to visualize this to a user.
A user should see that
items are in Queue
item processing has started
result of processing (mainly passed/failed/exception)
And now I got some headache.
I was thinking to do the following:
Have a Grid to display the items to users.
If item is Enqueued add it to workunits and additionally to a list bound to the datagrid
If item is Dequeued (consumed) update the item in the list for the grid.
What makes the headache, is how to make this thread safe, and which parts are needed to be thread safe.
If I put something which takes time behind workUnit.Add I think it could be possible, that data gets mixed.
Would something like this be feasible?
If item is Enqueued add it to workunits and an additional BlockingCollection for UI
If item is Dequeued, make a tryget on 2. BlockingCollection and remove it there, update the status and attach it to second list again.
Would I need an additional lock aound 1 and 2? If so, wouldn't it block completly the add if waiting for Take?
Is there an easy solution or approach to visualize, what is going on?

I will try do it this way:
public class MyClass
{
private BlockingCollection<workUnit> workUnits = new BlockingCollection<workUnit>();
public void EnQueue(workUnit item)
{
workUnits.Add(item);
}
private void DeQueue()
{
while (!stopFlag)
{
workUnit item = workUnits.Take();
item.SetState("Processing Started");
try
{
DoLongRunningDBStuff(workUnit);
item.SetState("Processing Successful");
}
catch
{
item.SetState("Processing Failed");
}
}
}
}
in this example I would then make workItem.SetState(...) fire an event that will update UI for the particular item. However, because the event is raised in a non-UI thread, it will be the handler of the event (the form displaying the grid I would assume) that would need to post the update into the context of the UI thread (e.g. If you are using WinForms you would call the Invoke method of the control displaying the data).
In another (preferred) suggestion I would do the following (if you can use the TPL in .NET 4.0 and later):
public class MyClass
{
public Task EnQueue(workUnit item)
{
// Schedule the work on the thread pool.
// If you need limited concurrency here, there are schedulers to enable this.
return Task.Run(() => DoLongRunningDBStuff(item));
}
}
And if you use .NET 4.5 you would be able to use the await feature that would automatically synchronise the continuation of the task in the context of the UI thread. E.g. in the on the caller's side (assuming it is initiated on the UI thread) you would simply do the following:
private async void btnAddItem_Click(object sender, EventArgs e)
{
var item = new workUnit();
// TODO: Add item on UI here
try
{
await myClass.EnQueue(item);
// TODO: Update UI with success result here (no context synchronisation is needed here it is already in the UI context)
}
catch
{
// TODO: Update UI with error result here (no context synchronisation is needed here it is already in the UI context)
}
}
In both examples you do not even need any locking, you simply need to have the updates posted to the correct context (and in the last example that is not even explicitly needed, the compiler takes care of it for you)

Related

Multi-threading with WPF ui

I'm not sure if this is possible, but I couldn't find anything when I searched about it.
I have a visual schedule made in WPF that loads and displays appointments. The problem is that it takes a while to load all the visuals and the program becomes unresponsive during that time.
Is it possible to load the appointment visuals and modify the schedule grid in a separate thread while leaving the main thread open for other things? Or possibly keep the schedule grid permanently in a second STA thread so it can do its own thing without interfering with the window?
edit:
Currently what I have:
private static void FillWeek()
{
BindingOperations.EnableCollectionSynchronization(ObservableAppointments, _lockobject);
for (int i = 1; i < 6; i++)
{
FillDay(Date.GetFirstDayOfWeek().AddDays(i).Date);
}
}
private static ObservableCollection<AppointmentUIElement> ObservableAppointments = new ObservableCollection<AppointmentUIElement>();
private static object _lockobject = new object();
public static async Task FillDay(DateTime date)
{
ClearDay(date);
Appointment[] Appointments;
var date2 = date.AddDays(1);
using (var db = new DataBaseEntities())
{
Appointments = (from Appointment a in db.GetDailyAppointments(2, date.Date) select a).ToArray();
}
await Task.Run(()=>
{
foreach (Appointment a in Appointments)
{
var b = new AppointmentUIElement(a, Grid);
ObservableAppointments.Add(b);
}
});
}
private static void ObservableAppointments_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
var a = e.NewItems[0] as AppointmentUIElement;
a.Display();
}
}
private static void ClearDay(DateTime date)
{
var Queue = new Queue<AppointmentUIElement>(Grid.Children.OfType<AppointmentUIElement>().Where(a => a.Appointment.Start.DayOfWeek == date.DayOfWeek));
while (Queue.Count > 0)
{
var x = Queue.Dequeue();
Grid.Children.Remove(x);
ObservableAppointments.Remove(x);
}
var Queue2 = new Queue<GridCell>(Grid.Children.OfType<GridCell>().Where(g => g.Date.Date == date));
while (Queue2.Count > 0)
{
Queue2.Dequeue().AppointmentUIElements.RemoveAll(a => true);
}
}
AppointmentUIElement is derived from Border
Yes
Now the challenge of all this is that visual elements and bound ObservableCollections can only be modified by the UI thread without some additional work. Bound properties that are not collections do not require this.
So lets say you have the "appointment visuals" from the UI bound to an ObservableCollection that has you appointment data in it. What you can do is make your 'search appointments' function async and register your collection for thread synchronization as below. I'm leaving out anything related to INotifyPropertyChange for brevity.
public ObservableCollection<Appointments> Appointments = new ObservableCollection<Appointments>();
private static object _lockobject = new object();
public async Task Load()
{
await Task.Run(() => { /*load stuff into the Appointments collection here */ });
///possibly more code to execute after the task is complete.
}
//in constructor or similar, this is REQUIRED because the collection is bound and must be synchronized for mulththreading operations
BindingOperations.EnableCollectionSynchronization(YourCollection, _lockobject);
There is also a much nastier and not recommended way of modifying UI thread created visual elements.
this.Dispatcher.Invoke(() => {/* do stuff with ui elements or bound things*/});
The gist of what happens is that you call load from the UI thread and when it hits the 'await task.run' it will work the contents of the task in a seperate thread while allowing the UI thread to continue responding to the user. Once the task completes it will then under the hood return to the ui thread to execute whatever else was under it in the load method.
If you forget the EnableCollectionSynchronization part then any attempts to add or remove items inside the task.run will throw an error complainging that you cannot change the contents of a collection in a different thread then the same one it was created with (almost same error as trying to modify a ui element directly).
Comment reply -> the problem with what your doing is here
AppointmentUIElement(a,Grid)
What you really should be doing here is putting the Grid into a custom control that has a bound item template defined that binds to items from the ObservableAppointments which should actually be the appointment data, not UI elements. All of this should be happening through ViewModels on context. The way your doing it will ONLY work if there is just a single thread managing EVERYTHING, as soon as another thread gets involved it will all fall apart on you.
Is it possible to load the appointment visuals and modify the schedule grid in a separate thread while leaving the main thread open for other things? Or possibly keep the schedule grid permanently in a second STA thread so it can do its own thing without interfering with the window?
You could load and display the schedule grid in a separate window that runs on a dedicated dispatcher thread. Please refer to this blog post for an example of how to launch a WPF window in a separate thread.
Keep in mind that an element created on the new thread won't be able to interact with an element created on the main thread though. So you can't simply load the schedule on another thread and then bring it back to the main thread. A visual element can only be accessed from the thread on which it was originally created on.

Async with part in UI

I have a task, which executed async, in part of this task add items in UI run via Dispatcher.BeginInvoke where i update a ObservebleCollection. For thread safe access to collection, i use a semaphoreSlim, but as request to Collection proceed in UI thread and Dispatcher.BeginInvoke also work in UI thread, i receive a dead lock.
private readonly ObservebleCollection<String> parameters = new ObservebleCollection<String>();
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(0, 1);
//Called from UI
public ObservebleCollection<String> Parameters
{
get
{
semaphore.Wait();
var result = this.parameters;
semaphore.Release();
return result;
}
}
public async Task Operation()
{
await semaphore.WaitAsync();
List<String> stored = new List<String>();
foreach (var parameter in currentRobot.GetParametersProvider().GetParameters())
{
stored.Add(parameter.PropertyName);
}
//Can't do add all items in UI at once, because it's take a long time, and ui started lag
foreach (var model in stored)
{
await UIDispatcher.BeginInvoke(new Action(() =>
{
this.parameters.Add(model);
}), System.Windows.Threading.DispatcherPriority.Background);
}
semaphore.Release();
}
And how i received a dead lock:
When i click a button in my program, Operation executed.
When i click a another button, program try access to Parameters property.
And i received a dead lock =D
Problem: in async operation i fill a observeblecollection via Dispatcher.BeginInvoke for each item separately, because if i add all items at once using Dispatcher, UI will lag. So i need a synchronization method for access to a Parameters property, which will wait until Operation ends.
await ensures the code after it will run in the original Synchronization context, in this case, in the UI thread. This makes BeginInvoke unnecessary as the code already runs on the correct thread.
The result is that you are trying to acquire two locks on the same object from the same thread, resulting in deadlock.
If you want thread-safe access to a collection of objects, avoid manually creating locks and use a thread-safe collection like ConcurrentQueue or ConcurrentDictionary.
Apart from that, I can't say I understand what the code tries to achieve as it does nothing in the background or asynchronously. It could easily be a simple method that copies parameters from one collection to another and it would still be thread safe if written properly. You could just write:
var _parameters=new ConcurrentQueue<string>();
....
public void CopyParameters()
{
foreach (var parameter in currentRobot.GetParametersProvider().GetParameters())
{
_parameters.Enqueue(parameter.PropertyName);
}
}
If you use databinding on the Parameters property, just raise PropertyChanged after you add all entries
What is the real problem you are trying to solve?
UPDATE
It seems the real problem is the UI freezes if you try to add too many items at a time. This isn't a threading problem, it's a WPF problem. There are various solutions, all of which involve raising PropertyChanged only after you finish adding all properties.
If you don't need the old values, just create a list with the new values, replace the old values then raise the PropertyChanged event, eg:
private ObservebleCollection<String> _parameters = new ObservebleCollection<String>();
public ObservebleCollection<String> Parameters
{
get
{
return _parameters;
}
private set
{
_parameters=value;
PropertyChanged("Parameters");
}
public void CopyParameters()
{
var newParameters=currentRobot.GetParametersProvider()
.GetParameters()
.Select(p=>p.PropertyName);
Parameters=new ObservableCollection<string>(newParameters);
}
Unless you have code that modified Parameters one item at a time though, you could easily swap ObservableCollection for any other collection type, even a string[] array.
Another option is to subclass ObservableCollection to add support for AddRange, as shown in this SO question

Is there such a synchronization tool as "single-item-sized async task buffer"?

Many times in UI development I handle events in such a way that when an event first comes - I immediately start processing, but if there is one processing operation in progress - I wait for it to complete before I process another event. If more than one event occurs before the operation completes - I only process the most recent one.
The way I typically do that my process method has a loop and in my event handler I check a field that indicates if I am currently processing something and if I am - I put my current event arguments in another field that is basically a one item sized buffer and when current processing pass completes - I check if there is some other event to process and I loop until I am done.
Now this seems a bit too repetitive and possibly not the most elegant way to do it, though it seems to otherwise work fine for me. I have two questions then:
Does what I need to do have a name?
Is there some reusable synchronization type out there that could do that for me?
I'm thinking of adding something to the set of async coordination primitives by Stephen Toub that I included in my toolkit.
So first, we'll handle the case that you described in which the method is always used from the UI thread, or some other synchronization context. The Run method can itself be async to handle all of the marshaling through the synchronization context for us.
If we're running we just set the next stored action. If we're not, then we indicate that we're now running, await the action, and then continue to await the next action until there is no next action. We ensure that whenever we're done we indicate that we're done running:
public class EventThrottler
{
private Func<Task> next = null;
private bool isRunning = false;
public async void Run(Func<Task> action)
{
if (isRunning)
next = action;
else
{
isRunning = true;
try
{
await action();
while (next != null)
{
var nextCopy = next;
next = null;
await nextCopy();
}
}
finally
{
isRunning = false;
}
}
}
private static Lazy<EventThrottler> defaultInstance =
new Lazy<EventThrottler>(() => new EventThrottler());
public static EventThrottler Default
{
get { return defaultInstance.Value; }
}
}
Because the class is, at least generally, going to be used exclusively from the UI thread there will generally need to be only one, so I added a convenience property of a default instance, but since it may still make sense for there to be more than one in a program, I didn't make it a singleton.
Run accepts a Func<Task> with the idea that it would generally be an async lambda. It might look like:
public class Foo
{
public void SomeEventHandler(object sender, EventArgs args)
{
EventThrottler.Default.Run(async () =>
{
await Task.Delay(1000);
//do other stuff
});
}
}
Okay, so, just to be verbose, here is a version that handles the case where the event handlers are called from different threads. I know you said that you assume they're all called from the UI thread, but I generalized it a bit. This means locking over all access to instance fields of the type in a lock block, but not actually executing the function inside of a lock block. That last part is important not just for performance, to ensure we're not blocking items from just setting the next field, but also to avoid issues with that action also calling run, so that it doesn't need to deal with re-entrancy issues or potential deadlocks. This pattern, of doing stuff in a lock block and then responding based on conditions determined in the lock means setting local variables to indicate what should be done after the lock ends.
public class EventThrottlerMultiThreaded
{
private object key = new object();
private Func<Task> next = null;
private bool isRunning = false;
public void Run(Func<Task> action)
{
bool shouldStartRunning = false;
lock (key)
{
if (isRunning)
next = action;
else
{
isRunning = true;
shouldStartRunning = true;
}
}
Action<Task> continuation = null;
continuation = task =>
{
Func<Task> nextCopy = null;
lock (key)
{
if (next != null)
{
nextCopy = next;
next = null;
}
else
{
isRunning = false;
}
}
if (nextCopy != null)
nextCopy().ContinueWith(continuation);
};
if (shouldStartRunning)
action().ContinueWith(continuation);
}
}
Does what I need to do have a name?
What you're describing sounds a bit like a trampoline combined with a collapsing queue. A trampoline is basically a loop that iteratively invokes thunk-returning functions. An example is the CurrentThreadScheduler in the Reactive Extensions. When an item is scheduled on a CurrentThreadScheduler, the work item is added to the scheduler's thread-local queue, after which one of the following things will happen:
If the trampoline is already running (i.e., the current thread is already processing the thread-local queue), then the Schedule() call returns immediately.
If the trampoline is not running (i.e., no work items are queued/running on the current thread), then the current thread begins processing the items in the thread-local queue until it is empty, at which point the call to Schedule() returns.
A collapsing queue accumulates items to be processed, with the added twist that if an equivalent item is already in the queue, then that item is simply replaced with the newer item (resulting in only the most recent of the equivalent items remaining in the queue, as opposed to both). The idea is to avoid processing stale/obsolete events. Consider a consumer of market data (e.g., stock ticks). If you receive several updates for a frequently traded security, then each update renders the earlier updates obsolete. There is likely no point in processing earlier ticks for the same security if a more recent tick has already arrived. Thus, a collapsing queue is appropriate.
In your scenario, you essentially have a trampoline processing a collapsing queue with for which all incoming events are considered equivalent. This results in an effective maximum queue size of 1, as every item added to a non-empty queue will result in the existing item being evicted.
Is there some reusable synchronization type out there that could do that for me?
I do not know of an existing solution that would serve your needs, but you could certainly create a generalized trampoline or event loop capable of supporting pluggable scheduling strategies. The default strategy could use a standard queue, while other strategies might use a priority queue or a collapsing queue.
What you're describing sounds very similar to how TPL Dataflow's BrodcastBlock behaves: it always remembers only the last item that you sent to it. If you combine it with ActionBlock that executes your action and has capacity only for the item currently being processed, you get what you want (the method needs a better name):
// returns send delegate
private static Action<T> CreateProcessor<T>(Action<T> executedAction)
{
var broadcastBlock = new BroadcastBlock<T>(null);
var actionBlock = new ActionBlock<T>(
executedAction, new ExecutionDataflowBlockOptions { BoundedCapacity = 1 });
broadcastBlock.LinkTo(actionBlock);
return item => broadcastBlock.Post(item);
}
Usage could be something like this:
var processor = CreateProcessor<int>(
i =>
{
Console.WriteLine(i);
Thread.Sleep(i);
});
processor(100);
processor(1);
processor(2);
Output:
100
2

Multi-threading problem when checking the list Count property

I have List newJobs. Some threads add items to that list and other thread removes items from it, if it's not empty. I have ManualResetEvent newJobEvent which is set when items are added to the list, and reset when items are removed from it:
Adding items to the list is performed in the following way:
lock(syncLock){
newJobs.Add(job);
}
newJobEvent.Set();
Jobs removal is performed in the following way:
if (newJobs.Count==0)
newJobEvent.WaitOne();
lock(syncLock){
job = newJobs.First();
newJobs.Remove(job);
/*do some processing*/
}
newJobEvent.Reset();
When the line
job=newJobs.First()
is executed I sometimes get an exception that the list is empty. I guess that the check:
if (newJobs.Count==0)
newJobEvent.WaitOne();
should also be in the lock statement but I'm afraid of deadlocks on the line newJobEvent.WaitOne();
How can I solve it?
Many thanks and sorry for the long post!
You are right. Calling WaitOne inside a lock could lead to a deadlock. And the check to see if the list is empty needs to be done inside the lock otherwise there could be a race with another thread trying to remove an item. Now, your code looks suspiciously like the producer-consumer pattern which is usually implemented with a blocking queue. If you are using .NET 4.0 then you can take advantage of the BlockingCollection class.
However, let me go over a couple of ways you can do it youself. The first uses a List and a ManualResetEvent to demonstrate how this could be done using the data structures in your question. Notice the use of a while loop in the Take method.
public class BlockingJobsCollection
{
private List<Job> m_List = new List<Job>();
private ManualResetEvent m_Signal = new ManualResetEvent(false);
public void Add(Job item)
{
lock (m_List)
{
m_List.Add(item);
m_Signal.Set();
}
}
public Job Take()
{
while (true)
{
lock (m_List)
{
if (m_List.Count > 0)
{
Job item = m_List.First();
m_List.Remove(item);
if (m_List.Count == 0)
{
m_Signal.Reset();
}
return item;
}
}
m_Signal.WaitOne();
}
}
}
But this not how I would do it. I would go with the simplier solution below with uses Monitor.Wait and Monitor.Pulse. Monitor.Wait is useful because it can be called inside a lock. In fact, it is suppose to be done that way.
public class BlockingJobsCollection
{
private Queue<Job> m_Queue = new Queue<Job>();
public void Add(Job item)
{
lock (m_Queue)
{
m_Queue.Enqueue(item);
Monitor.Pulse(m_Queue);
}
}
public Job Take()
{
lock (m_Queue)
{
while (m_Queue.Count == 0)
{
Monitor.Wait(m_Queue);
}
return m_Queue.Dequeue();
}
}
}
Not answering your question, but if you are using .NET framework 4, you can use the new ConcurrentQueue which does all the locking for you.
Regarding your question:
One scenario that I can think of causing such a problem is the following:
The insertion thread enters the lock, calls newJob.Add, leaves the lock.
Context switch to the removal thread. It checks for emptyness, sees an item, enters the locked area, removes the item, resets the event - which hasn't even been set yet.
Context switch back to the insertion thread, the event is set.
Context switch back to the removal thread. It checks for emptyness, sees no items, waits for the event - which is already set, trys to get the first item... Bang!
Set and reset the event inside the lock and you should be fine.
I don't see why object removal in case of zero objects should wait for one to be added and then remove it. It looks to be being against logic.

What is the best way to thread work in c#?

What's the best way to thread work (methods) in c#?
For example:
Let's say I have a form and want to load data from db.
My form controls:
- dataGridView (to show data from DB),
- label (loading status) and
- button (start loading).
When I click the button my form is frozen until the task is done. Also the loading status does not change until task is done. I think async threading would be the answer?
So my question: what's the best way to handle this? I know there is a lot stuff about Threading, but what's the difference between them and how do you make it thread safe?
How do you solve this kind of problems?
Best Regards.
If using Windows Forms, you should look at BackrgroundWorker. More generally, it is often useful to use the ThreadPool class. And finally, it is worth to take a look at the new .NET 4's Parallel class.
There is no universal 'best' way to thread work. You just have to try different ways of doing things, I'm afraid.
I particularly like Jeremy D. Miller's continuation idea described at this page (scroll down to find the "continuations" section). It's really elegant and means writing very little boilerplate code.
Basically, when you call "ExecuteWithContinuation" with a Func argument, the function is executed asynchronously, then returns an action when it finishes. The action is then marshalled back onto your UI thread to act as a continuation. This allows you to quickly split your operations into two bits:
Perform long running operation that shouldn't block the UI
... when finished, update the UI on the UI thread
It takes a bit of getting used to, but it's pretty cool.
public class AsyncCommandExecutor : ICommandExecutor
{
private readonly SynchronizationContext m_context;
public AsyncCommandExecutor(SynchronizationContext context)
{
if (context == null) throw new ArgumentNullException("context");
m_context = context;
}
public void Execute(Action command)
{
ThreadPool.QueueUserWorkItem(o => command());
}
public void ExecuteWithContinuation(Func<Action> command)
{
ThreadPool.QueueUserWorkItem(o =>
{
var continuation = command();
m_context.Send(x => continuation(), null);
});
}
}
You'd then use it like this (forgive the formatting...)
public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished()
{
DisableUi();
m_commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
ConnectToServer();
// This is the continuation that will be run
// on the UI thread
return () =>
{
EnableUi();
};
});
}
You can use this kind of pattern:-
private void RefreshButton_Click(object sender, EventArgs e)
{
MessageLabel.Text = "Working...";
RefreshButton.Enabled = false;
ThreadPool.QueueUserWorkItem(delegate(object state)
{
// do work here
// e.g.
object datasource = GetData();
this.Invoke((Action<object>)delegate(object obj)
{
// gridview should also be accessed in UI thread
// e.g.
MyGridView.DataSource = obj;
MessageLabel.Text = "Done.";
RefreshButton.Enabled = true;
}, datasource);
});
}
You cannot access your controls from the code that runs in the spun-off thread - the framework does not allow this, which explains the error you are getting.
You need to cache the data retrieved from the db in a non-forms object and populate your UI with data from that object after the background worker thread is done (and handle synchronization for access to that object).

Categories