Here is my scenario.
I have the following line of code in my program:
JCL_History.Enqueue(JCL_History(I))
This JCL_History object is basically a Generic.List encapsulated in a wrapper and has the following method:
Public Sub Enqueue(ByRef value As String)
If Members.Contains(value) Then
Me.RemoveAt(Members.IndexOf(value))
ElseIf _Count = _MaxCount Then
Me.RemoveAt(_Count - 1)
End If
Me.Insert(0, value)
End Sub
So you see that the first line of code that invokes Enqueue should "shuffle" items around.
Also, the wrapper class of which JCL_History is a type has the following default property:
Default Public Property Item(ByVal Index As Integer) As String 'Implements Generic.IList(Of String).Item
Get
If Index < _MaxCount Then
Return Members(Index)
Else
Throw New IndexOutOfRangeException("Bug encountered while accessing job command file history, please send an error report.")
End If
End Get
Set(ByVal value As String)
If Index < _MaxCount Then
If Index = _Count Then _Count = _Count + 1
Members(Index) = value
Else
Throw New IndexOutOfRangeException("Bug encountered while accessing job command file history, please send an error report.")
End If
End Set
End Property
In my testing I have 2 items in this JCL_History list. When I call that first line of code I posted (the one that invokes Enqueue) with I = 1 I expect the first item to be shuffled to the bottom and the second item to be shuffled to the top.
After the thread returns from Enqueue I notice that this is exactly what happens to my list, HOWEVER if I hit the "step_in" button after the execution of Enqueue I go into the Default Property's set method where Index = 1 and value = and it screws everything up, because the item that got shuffled to the end (index 1) gets overwritten by the item value shuffled to the top.
So basically the set method on the default property is getting called at what I think to be a completely ridiculous time. What gives? By the way I'm running VS2005 on XP.
Do you have a watch and/or are you executing a quick watch via a mouse-over that would read a property that might invoke the Set? If your debugging environment evaluates something that changes data, you can get weird behavior like what you're describing.
Whether or not the case above is true, if multiple threads can write to Members, consider using ReaderWriterLockSlim.
No answer. Never fixed this, just worked around it.
Related
I have been developing a project that is similar to the task assigning project which uses the chained through time pattern. I have a difficulty comparator that prioritizes the tasks that must be finished earlier. My problem is that whenever a new entity is added to the chain, it's added to the top, pushing down the tasks that must be done earlier.
Is that supposed to happen? or is my implementation bad?
This is my code in the listener. It's basically the same as in the task assigning project.
protected void updateStartTime(ScoreDirector scoreDirector,Calcado calcado){
CalcadoA calcadoAnterior = calcado.getCalcadoAnterior();
Calcado shadowCalcado = calcado;
Integer previousEndTime = (calcadoAnterior == null ? null : calcadoAnterior.getEndTime());
Integer startTime = previousEndTime;
while (shadowCalcado != null && !Objects.equals(shadowCalcado.getStartTime(), startTime)) {
scoreDirector.beforeVariableChanged(shadowCalcado, "startTime");
shadowCalcado.setStartTime(startTime);
scoreDirector.afterVariableChanged(shadowCalcado, "startTime");
previousEndTime = shadowCalcado.getEndTime();
shadowCalcado = shadowCalcado.getNextCalcado();
startTime = previousEndTime;
}
I have tried changing it to this...
protected void updateStartTime(ScoreDirector scoreDirector,Calcado calcado) {
CalcadoA calcadoAnterior = calcado.getCalcadoAnterior();
Calcado shadowCalcado = calcado;
Integer previousEndTime = (calcadoAnterior == null ? null : calcadoAnterior.getEndTime());
Integer startTime = previousEndTime;
scoreDirector.beforeVariableChanged(shadowCalcado, "startTime");
shadowCalcado.setStartTime(startTime);
scoreDirector.afterVariableChanged(shadowCalcado, "startTime");
}
but I end up getting a score corruption error.
The entity (Calcado{ 472 descricao= calcado22 tempoInicial: 2 Maquina{nome='Pos 1'}'})'s shadow variable (Calcado.startTime)'s corrupted value (1) changed to uncorrupted value (2) after all VariableListeners were triggered without changes to the genuine variables.
Maybe the VariableListener class (StartTimeUpdatingVariableListener) for that shadow variable (Calcado.startTime) forgot to update it when one of its sources changed.
Basically my goal is to whenever a entity is added to the chain, to be added to the end of the chain instead of the top.
Yes, that's suppose to happen.
An entity isn't really added to a chain, that's a side effect.
It's inserted after another entity or anchor. That entity or anchor is already in a chain, so it implies that the entity is also added to a chain.
Why does that matter? Well, given a chain of [Anchor-A, Entity-A1, Entity-A2, Entity-A3], OptaPlanner can choose to add an Entity-X after Anchor-A, Entity-A1, Entity-A2 or Entity-A3, resulting in 4 different possible new solution states. It will pick the best one. Turn on TRACE logging to see that happen.
I am working on a little framework and I want to have a class file that contains functions I can run to check if a certain key has been pressed so other events can be run. The only code I have found online for similar things are written into the form itself and use something like "Handles Me.KeyPress". However, this handle function can't be used in a class file.
Public Function OnKeyPress(KeyToCheck As Keys)
If KeyPressed = KeyToCheck then
return true
else
return false
End If
End Function
I have tried:
Public Function OnKeyPress(KeyToCheck As Keys)Handles Formname.Keypress
If KeyPressed = KeyToCheck then
return true
else
return false
End If
End Function
However, this does not work. Any suggestions or work arounds would be greatly appreciated.
To get keyboard input, you need to have a window. All input goes to a window, and that window can then check for key presses that are sent to it.
To get global information, you'd need to install a hook, but those should generally be avoided.
In my code I use this line to Initialize my Base:
MyBase.Initialize(name, config)
Everything goes fine in the first time pass... but when it passes second time then throws me an error The Base Is already Initialized and that is something I don't want to happen.
Is there any way to catch this event?
Finally the Base initialized only in the Default.aspx page, putting these lines in the Page_Load:
Dim myNewAsp As New AspNetSqlProvider
If MyAspNetSqlMembershipProvider.SQLconnectionString = Nothing Then
myNewAsp.InitializeSite(sender, e)
Return
End If
Doing this the system always knows when if the Base is initialized or not.
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.
Currently I am having a weird problem which I simply do not understand. I have a simple GUI, with one button & one richeditbox. I have an async socket running, I am receiving some data over the network which I want to print to the gui(richeditbox). The async socket is being started when the user hits the button. So when I receive the network data I call a function which prints the data, here how it looks like (in form1 class):
Public Sub AddText(ByVal text As String)
Try
Console.WriteLine(text)
RichTextBox1.AppendText(text)
RichTextBox1.AppendText(vbNewLine)
Catch e As Exception
Console.WriteLine(e.ToString())
End Try
End Sub
Then I simply do Form1.AddText(..) from my network class or a module (does it matter?). The problem is that nothing appears in the richeditbox, even though the AddText function is being called, no exceptions, no errors, simply nothing. I've looked thru it with the debugger, and "text" contained the data it had to print, but simply nothing appears.. Anyone have an idea?
If the socket is running on another thread (which, of course, it is because it's asynchronous), you may have to use InvokeRequired in order to get the RichTextBox to display the text. I had a similar issue with a listener on an asynchronous serial port listener.
I'm pretty sure David is right. Here's an example.
Delegate Sub AddTextDelegate(ByVal text as String)
Public Sub AddText(ByVal text as String)
If Me.InvokeRequired Then
Me.Invoke(new AddTextDelegate(AddressOf Me.AddText), new object() { text })
Else
Try
Console.WriteLine(text)
RichTextBox1.AppendText(text)
RichTextBox1.AppendText(vbNewLine)
Catch e as Exception
Console.WriteLine(e.ToString())
End Try
End If
End Sub
The deal is that controls have to be updated on the thread they were created on. It sounds like the AddText() routine is being called in the context of your async socket's thread. The AddText() routine will behave like a recursive function. The first time it's called, the InvokeRequired property will be true. This will cause it to be called again via the Invoke() call, which takes care of marshaling the data to the correct thread. The second time it's called, InvokeRequired will be false, and the control will be updated.
Fixed. I couldn't use Form1 to call the functions, because it's a type, its like a new var there with its own memory, since its a diff thread. So when I checked InvokeRequired, it said false because that Form1 belongs to that Thread, and thus no text was being displayed because I didn't even see the form. So just made a global var such as Public myForm As Form1 and assigned myForm to Form1 in Form1_Load.