I want to set an event handler only if this is not set:
If GetHandlers(MyWindow.Closed, AddressOf MyWindow_Closed).Length = 0 Then
AddHandler MyWindow.Closed, AddressOf MyWindow_Closed
EndIf
You can't really query the current value of the event's delegate, except in the code that defines the event. What is your intent here? Normally you shouldn't be too concerned (necessarily) with other subscribers? There are ways of hacking past the encapsulation to find the current value, but they are not recommended (it just isn't a good idea).
If your concern is whether you are already handling that event with that handler (i.e. you don't want to double-subscribe, then you can always either a: fix the code so it doesn't do this, or b: cheat (C# example):
// remove handler **if subscribed**, then re-subscribe
myWindow.Closed -= MyWindow_Closed;
myWindow.Closed += MyWindow_Closed;
To get the invocation list is... brittle but doable. In simple cases you can just use reflection to get the field, and snag the value. But with forms etc it uses sparse techniques (to minimise the space for events without subscribers). In the case of FormClosed, this is keyed via EVENT_FORMCLOSED.
It might make more sense with an example (C#, sorry):
Form form = new Form();
form.FormClosed += delegate { Console.WriteLine("a");}; // just something, anything
form.FormClosed += delegate { Console.WriteLine("b");}; // just something, anything
object key = typeof(Form).GetField("EVENT_FORMCLOSED",
BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
EventHandlerList events = (EventHandlerList )
typeof(Component).GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(form, null);
FormClosedEventHandler handler = (FormClosedEventHandler)events[key];
foreach (FormClosedEventHandler subhandler in handler.GetInvocationList())
{
subhandler(form, null); // access the two events separately
}
In the case of an ObservableCollection<T>, the delegate is directly on a field, so less indirection is required:
ObservableCollection<SomeType> list = ...
NotifyCollectionChangedEventHandler handler = (NotifyCollectionChangedEventHandler)
list.GetType()
.GetField("CollectionChanged", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(list);
Related
onValue "subscribes a given handler function to event stream. Function will be called for each new value in the stream. [It] is the simplest way to assign a side-effect to a stream."
On the other hand, doAction "returns a stream/property where the function f is executed for each value, before dispatching to subscribers."
It sounds like these both just execute a function on each value in a stream. What is different between them?
The difference is that doAction returns the same stream, allowing you to chain side-effects, while onValue is a subscribe-like function (and thus returns an unsubscribe function).
[I had intended to ask this question for real, and then realized the answer as I began to write it down. In case anyone else finds themselves in a similar situation, perhaps this will save them a few minutes.]
The big difference is that onValue subscribes to the stream, doAction does not. If there are no subscribers, the function inside doAction never gets called.
var numbers1 = Bacon.fromArray([1,2,3])
numbers1.doAction(function(number) {
alert("doAction Number " + number) // This never gets called
})
var numbers2 = Bacon.fromArray([1,2,3])
numbers2.onValue(function(number) {
alert("onValue Number " + number) // This gets called
})
var numbersBoth = Bacon.fromArray([1,2,3])
numbersBoth
.doAction(function(number) { console.log(number) }) // gets called
.onValue(function(number) {
// Do something with number
})
In practice I only use doAction for debugging. If you want to split your side effects to separate functions, you can add multiple onValue handlers (except for synchronous streams, but they can be made async with a simple .delay(0))
I've got a contributed command and a handler for it. The handler's execute event has to get the value for the property actually selected in the properties view and act on it, or to be disabled if no property selected.
I've tried:
1) Set the selection provider to something which provides selection from the property view. Something in this case is just PropertySheetViewer for my PropertySheetPage, but i can't set it as the selection provider because the PropertySheetPage's viewer is private and has no getter.
2) Overriding PropertySheetPage's createControl method: This method creates a Tree control for the PropertySheetViewer. A selection listener can be installed for that tree control, so maybe i can make my command handler implement SelectionListener... The solution would be somethin like:
In my editor:
public Object getAdapter(#SuppressWarnings("rawtypes") Class type) {
if (type == IPropertySheetPage.class) {
PropertySheetPage page = new PropertySheetPage() {
#Override
public void createControl(Composite parent) {
super.createControl(parent);
IHandler handler = someWayToGetMyCmdHandler();
((org.eclipse.swt.widgets.Tree) getControl())
.addSelectionListener(handler);
}
};
IPropertySheetEntry entry = new UndoablePropertySheetEntry(
getCommandStack());
page.setRootEntry(entry);
return page;
}
return super.getAdapter(type);
}
And my command handler implementing SelectionListener as i said... The problem with this approach is that i can't find a way to get a reference to my contributed command handler (someWayToGetMyCmdHandler() above).
Has anybody got any clue on this, or any other possible approach to the problem??
There's handleEntrySelection(ISelection selection) method in PropertySheetPage that you could override to be notified about selection changes in the viewer (although PropertySheetPage is #noextend).
The second part (updating the handler) is a bit more tricky than it would normally be. Commands/handlers get updated automatically when workbench selection changes (you just need to implement setEnabled(Object evaluationContext) AbstractHandler). But since PropertySheetPage is designed to change its input on global selection change, then you have to find some custom way to notify/update your handler.
As I understand, it is currently not possible to extend the platform command event handling mechanism with custom variables, so you just need to directly look up your handler using IHandlerService of the workbench.
I have a class written in C#. In it I want to run a certain function in parallel on a list. After it completes on each item I would like to update a progress bar. However, I get very odd behavior from my program. It executes the event and reaches my sub but never proceeds to actually execute any code. Instead it just freezes. (I've mixed vb.net and c#. It will be rewritten at some point)
so in my windows form I call
progressBar.Visible = True
progressBar.Value = 0
progressBar.Maximum = dataGrid.SelectedRows.Count
AddHandler quoteManager.refreshStarted, AddressOf progressBarCounter
quoteManager.refreshAllAsync(list)
and the event is simply
Private Sub progressBarCounter()
Me.Invoke(Sub()
If progressBar.Value = progressBar.Maximum Then
progressBar.Visible = False
Else
progressBar.Value += 1
End If
End Sub)
End Sub
and in the quote manager class I have this defined.
public event Action refreshStarted;
public void refreshAllAsync(List<BindableQuote> bindableQuotes)
{
bindableQuotes.AsParallel()
.WithDegreeOfParallelism(10)
.ForAll((quote) => {
quote.refreshAll();
if (refreshStarted != null) { refreshStarted(); }
});
}
So for some reason I get it to enter progressBarCounter on each item in the list but it never exists. Instead it just keeps the form frozen.
I am not exactly sure this is what is happening, but it looks like progressBarCounter is blocking because you are calling Invoke. Should you be using BeginInvoke instead? Using BeginInvoke might solve the deadlock issue. See this post: What's the difference between Invoke() and BeginInvoke()
What appears to be happening here is that you access UI objects from multiple threads.
That's not supported. You'll have to run this code on a worker thread, and let it somehow accumulate progress, and send messages back to the UI thread. The BackgroundWorker class can help you implement the marshalling back to the UI thread.
I have an application with 4 threads. (GUI, Controller, Producer, Consumer)
The GUI is self-explanatory.
The controller starts the producer and consumer threads after some intial setup.
The producer creates items and places them in a free slot in a "ring buffer"
The consumer takes items from the "ring buffer" and writes them to disk.
The producer creates items at a much higher rate than the consumer.
The consumer is IO heavy and IO bound.
Currently I am checking a variable in each ring buffer slot to determine if it can be written to.
if Slot.Free then
Write Slot.Data To Disk
end if
I am not using lock/synclock instead I'm just reading / writing the value of the slot's "free" variable. I don't believe that is correct even though it is a volatile read/write. Is there a better method to read/write this variable? The variable is of type "integer" and is either 0 or 1.
You mention using a ring buffer, but a (properly implemented) ring buffer would be able to determine if it's full without checking all it's elements, eliminating the need for a boolean in each slot.
I'm not used to VB.NET, but this should be a working (if crude) implementation of a ring buffer that blocks when it's full / empty on respective write / read actions.
Friend Class RingBuffer(Of T)
Private _slots() As T
Private _head As Integer
Private _tail As Integer
Private _readableSlots As Semaphore
Private _readLock As Object
Private _writableSlots As Semaphore
Private _writeLock As Object
Public Sub New(ByVal size As Integer)
ReDim _slots(size - 1)
_head = 0
_tail = 0
_readLock = New Object
_writeLock = New Object
_readableSlots = New Semaphore(0, size)
_writableSlots = New Semaphore(size, size)
End Sub
Public Function Dequeue() As T
Dim item As T
_readableSlots.WaitOne()
SyncLock _readLock
item = _slots(_head)
_head = (_head + 1) Mod _slots.Length
End SyncLock
_writableSlots.Release()
Return item
End Function
Public Sub Enqueue(ByVal item As T)
_writableSlots.WaitOne()
SyncLock _writeLock
_slots(_tail) = item
_tail = (_tail + 1) Mod _slots.Length
End SyncLock
_readableSlots.Release()
End Sub
End Class
Once you have that, your Producer and Consumer can be really dumb :) It's not exactly guaranteed that items are processed in-order if you have multiple consumers however:
Private _buffer As RingBuffer(Of Integer) = New RingBuffer(Of Integer)(5)
Private Sub Producer()
Dim i As Integer = 0
Do While True
_buffer.Enqueue(i)
i = i + 1
Loop
End Sub
Private Sub Consumer()
Do While True
Debug.WriteLine(("Consumer A: " & _buffer.Dequeue))
Thread.Sleep(1000)
Loop
End Sub
There are several ways you can do this safely.
If your architecture and requirements allow it, you can use custom events so one thread can simply signal a different listening thread to notify that a variables state has been changed. You do have to keep track of who is consuming what events though, and if those consumers are read-only on the variable, or read/write.
You can also use a simple custom wrapper class around a variable type (or use a generic) that does the lock/unlock code for you. In VB.NET, I've found that using the Monitor class to lock the private instance variable is really handy.
Mutexes and semaphores - .NET has a Mutex class and a Semaphore class. These both assist in controlling access to thread-shared variables. I like Mutexes because they're so easy to use, and you don't need to keep track of how many threads might have access to a given resource.
Please DO note that although some MSDN documentation claims that reading to or writing from a value-type (Integer, Double, etc) is an atomic operation, and hence "thread-safe", this is SELDOM TRUE in actual VB code. A simple statement like X = Y is NOT in fact atomic, as it you have to perform two operations here - first, loading the value of Y, and then setting the value of X. Little things like this make me lose my hair :)
Whatever method you decide to roll with, I find that liberal commenting throughout your code describing who has access to what resources at what time is invaluable - three months from now, you're not gonna remember the fine points of this code and comments really help.
Best of luck!
You could use Semaphores to solve the Producer Consumer problem:
static void Main(string[] args)
{ new Thread(Producer).Start(); new Thread(Consumer).Start(); }
static int K = 10;
static n = new Semaphore(0, K), e = new Semaphore(K, K);
static int[] buffer = new int[K];
static int _in, _out;
static void Producer()
{
while (true)
{
e.WaitOne();
buffer[_in] = produce();
_in = (_in + 1) % buffer.Length;
n.Release();
}
}
static void Consumer()
{
while (true)
{
n.WaitOne();
var v = buffer[_out];
_out = (_out + 1) % buffer.Length;
e.Release();
consume(v);
}
}
Any time that data can be accessed by more than one thread, you have to write your code to assume that it will be accessed by more than one thread. "Murphy's Law" rules multithreaded scenarios.
For instance, if one thread is filling a slot, and the other is emptying it, you need a lock around it.
You can make your checks interlocked operations and eliminate any concern:
const FREE = 0;
const FILLING = 1;
const READY = 2;
const DRAINIG = 3;
Producer:
if (FREE == Interlocked.CompareExchange(ref slotFlag, FILLING, FREE))
{
fillslot();
old = Interlocked.Exchange(ref slotFlag, READY);
Debug.Assert (FILLING == old);
}
Consumer:
if (READY == Interlocked.CompareExchange(ref slotFlag, DRAINIG, READY))
{
drain_slot();
old = Interlocked.Exchange(ref slotFlag, FREE);
Debug.Assert( DRAINIG == old);
}
This is lock free and quite efficient if you have many cores, many producers and/or many consumers. The problem with this, that is also the problem with using bool, is that there are no wait semantics. Both the Producer and the Consumer will have to spin looking for FREE and respectively READY slots. You can overcome this by adding 'ready' and 'free' events. Also you need to take care of ensuring the ring buffer write/read positions are properly maintained.
I've got two dojo.dnd.Sources with items. Whenever an item is dropped I need to persist the new order of the items in the Sources using an xhr.
Is there an dojo event or topic that is fired after an dnd operation has (successfully) finished? What would be the best way to use it?
Probably I don't understand the problem in all details but I don't see why you need to process events or topics. The best way to record changes is to intercept updating methods on relevant sources. Specifically you need to intercept insertNodes() for drops or any other additions.
Simple example (pseudo-code):
var source1, source2;
// ...
// initialize sources
// populate sources
// ...
function getAllItems(source){
var items = source.getAllNodes().map(function(node){
return source.getItem(node.id);
});
return items;
}
function dumpSource(source){
var items = getAllItems(source);
// XHR items here to your server
}
function recordChange(){
// now we know that some change has occured
// it could be a drop or some programmatic updates
// we don't really care
dumpSource(source1);
dumpSource(source2);
}
dojo.connect(source1, "insertNodes", recordChanges);
dojo.connect(source2, "insertNodes", recordChanges);
// now any drop or other change will trigger recordChanges()
// after the change has occurred.
You can try to be smart about that and send some diff information instead of a whole list, but it is up to you to generate it — you have everything you need for that.
You can use dojo.subscribe to do something when a drop is finished like so:
dojo.subscribe("/dnd/drop", function(source, nodes, copy, target) {
// do your magic here
});
There's examples of using subscribe on the dojotoolkit tests site. More info about dojo publish and subscribe too.
Alternately, you could connect to the onDndDrop method.
var source = new dojo.dnd.Source( ... );
dojo.connect( source, "onDndDrop", function( source, nodes, copy, target ) {
// make magic happen here
});
connect methods are called at the end so the items will be there at that point.
I'm keeping this note for dojo Tree folks just like me who would run in to this problem. Solutions given here was not quite worked well in my situation. I was using a dijit.tree.dndSource with Dojo tree and subscribing to "/dnd/drop" allows me to capture the event even though at that point my underlying data store hadn't been updated with latest changes. So I tried waiting as Wienczny explains, that doesn't solve the problem completely as I can't rely on a timeout to do the waiting job. Time taken for store update could be vary, i.e. shorter or very long depends on how complex your data structure is. I found the solution with overriding the onDndDrop method of the dndController. Simply you can specify the onDndDrop : on your tree initialization. One thing I found odd though you can not hitch this method, you will get weird behavior during dnd.
Tree
this._tree = new MapConfigTree({
checkAcceptance: this.dndAccept,
onDndDrop: this.onDndDrop,
betweenThreshold:5,
method
onDndDrop : function(source, nodes, copy, target){
if(source.dropPosition === 'Over' && (target.targetAnchor.item.type[0] == 'Test layer')) {
this.inherited(arguments);
// do your bit here
} else {
this.onDndCancel();
}
}