how to bind Eclipse RCP Table View to other thread data - multithreading

I have just started with Eclipse RCP.
I created Eclipse RCP View with TableViewer and WritableList to get data from other thread.
But I cannot see any changes. I need only to show content of List that other thread is managing.
public class View extends ViewPart {
private TableViewer viewer;
private WritableList input;
I also can get error,
org.eclipse.core.runtime.AssertionFailedException: assertion failed: Getter called outside realm of observable org.eclipse.core.databinding.observable.list.WritableList
I know what is UI Thread. I just don't know how to write. Please help with example.
UPDATE. Was not solved, because of lack of time, and missing good and focused tutorial.

I received this error message also with my code.
Databinding observables (WritableList, WritableValue...) inherit from ChangeManager, which provides ChangeManager#getRealm and the realm has Realm#exec. Within the runnable provided to exec, the operation runs in the correct thread.
This line caused the error (Getter called outside realm of observable):
WritableValue value = getEditor().getWritableValue();
System.out.println(((RcpEditorModel) value.getValue()).getNumber());
And this prevented the exception:
WritableValue value = getEditor().getWritableValue();
value.getRealm().exec(() -> System.out.println(((RcpEditorModel) value.getValue()).getNumber()));
The same will work with WritableList since it also inherits from ChangeManager.

Related

Dynamics AX 2012 - Custom Lookup in a dialog

So, I am working on a class called DMFWriteExportData and trying to get it run in Batch.
I am at a point where I need to figure out a way to get rid of fieldControl and the reason being it does not let me Run the class on the server and throws an error because it is not supposed to be running on server? (not sure)
Error: "The method Dialog Control.control cannot be called from the server; use methods on the Dialog Field class instead."
-
public Object dialog()
{
DialogRunbase dialog = new DialogRunbase("#DMF372", this);
FormStringControl control;
dialogExecution = dialog.addFieldValue(extendedTypeStr(dMFExecutionId), executionId);
control = dialogExecution.fieldControl();
control.mandatory(true);
control.displayLength(24);
control.registerOverrideMethod(methodstr(FormStringControl, lookup), methodstr(DMFWriteExecutionParameters, executionIdLookup), this);
control.registerOverrideMethod(methodstr(FormStringControl, modified), methodstr(DMFWriteExecutionParameters, executionIdModified), this);
dialogdescription=dialog.addFieldValue(extendedTypeStr(description),DMFExecution::find(executionId).Description);
dialogdescription.enabled(false);
return dialog;
}
I am wondering:
If it is actually true that this class cannot be set to server
when using control.registerOverrideMethod
If yes, what would be the ideal solution to overcome this situation,
is there any way I can create custom lookups? I see there is method
called registerOverrideMethod in the DialogField class.
Any help would be appreciated.
Thanks,
Khosla
The reason why you cannot (and should) run the code above in batch is because it uses dialog controls that only exist on the client side. You should never run this kind of code on server. Please check runon property of your class and set it to called from.
However, I assume you are using RunBaseBatch. If you are on AX 2012, you should use the SysOperation framework instead.
When using RunBaseBatch, all code is on the same class. This way, you are mixing client side code (main method, dialog method etc) with the code that should run on server (run method). For this reason you should set the "runon" property of the class to CalledFrom, not Server.
You can solve this by using SysOperation which applies the Model View Controller (MVC) pattern that neatly sepperates the two.
For an introduction to SysOperation, check my blog here:
AX2012: SysOperation introduction

Accessing WinForm UI from Rhino Service Bus consumer [duplicate]

This question already has answers here:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created
(8 answers)
Closed 9 years ago.
I have a WinForm screen that is also a message consumer (using Rhino ESB). If I try to update anything on the screen when I receive a message, nothing happens. A call to Invoke gives me an error that the handle is not created. The form is definitely created though, I'm firing a message on button click on the form and the background process sends a message back. It's with this return message I want to update the UI.
THIS IS NOT A DUPLICATE QUESTION, NONE OF THE SUGGESTED SOLUTIONS WORK.
I believe the difference here may be because I'm using Rhino Service bus. Rhino may be constructing a separate instance of my form rather than the one I'm using. I think what I probably need to do is to have Rhino use my instance of the form as the consumer by passing my instance into the IoC container Rhino is using. Another alternative is to move the Consumer off to it's own class and inject my Form into the consumer, and put a public method on my Form for the Consumer to use. This may work fine with my app because this is the main form and will never be disposed unless the app is closed. This would become problematic on another form that may be instantiated multiple times. Perhaps I could have my form "observe" another static object that a separate Consumer class updates. Please give suggestions as to the best approach.
public partial class MainForm : Form, ConsumerOf<MoveJobCompletedEvent>
{
public void Consume(MoveJobCompletedEvent message)
{
// This does nothing!
txtLogs.Text = "\nJob completed!";
}
}
This throws an error:
this.BeginInvoke((MethodInvoker)delegate
{
txtLogs.Text += "\nJob job completed!";
});
ERROR: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
It seems that you're consuming a JobCompleted event before the window handle is created. You could try the following:
public partial class MainForm : Form, ConsumerOf<MoveJobCompletedEvent>
{
public void Consume(MoveJobCompletedEvent message)
{
if (!this.HandleCreated)
return;
this.BeginInvoke((MethodInvoker)delegate
{
txtLogs.Text += "\nJob job completed!";
});
}
}

How to make a Thread pause in Spring mvc project?

I am using a Thread in Spring mvc project to do some background working.
What I have done is
I write a class which extends Thread. and I added init() method to start this class.
Whole ThreadTest.java is Below.
package org.owls.thread.vo;
public class ThreadTest extends Thread {
public void init(){
this.start();
}
public void pause(){
this.interrupt();
}
#Override
public void run() {
for(int i = 0; i < 100; i++){
try{
Thread.sleep(3000);
System.out.println("Thread is running : " + i);
} catch(Exception e){e.printStackTrace();}
}
}
};
edit root-context.xml intent to start this Thread as soon as possible when the server started.
<bean id="threadTest" class="org.owls.thread.vo.ThreadTest" init-method="init"/>
Now is the problem. I want to make a toggle button(pause/resume) in my home.jsp and When I click the button it works. But I do not know how can I access to the Thread, which already registered and run.
please, show me the way~>0<
P.S
additional question about java Thread.
What method exactly means pause and resume. I thought stop is the one similar to pause, but it is deprecated.
And start() is somehow feels like 'new()' not resume.
Thanks
I figured out how to control a thread.
if I want to pause(not stop), code should be like below.
thread.suspend();
And want to resume this from where it paused, like below.
thread.resume();
even though those methods are both deprecated.
(if somebody knows some replacement of these, reply please)
If you do not want to yellow warning in your spring project,
you can remove warning by simply add an annotation on that method.
annotation is #SuppressWarnings("deprecated").
=========================================================
From here, additional solutions based on my experience.
To make automatic executing Spring mvc Thread,
I did following steps.
make a simple Class which extends Thread class.
inside that class, make a method. this will be calles by
config files. in this method. I wrote code like "this.start();".
Let Spring knows we have a Thread class that should run independently
with Web activities. To do this, we have to edit root-context.xml.
Add a bean like this.
<bean id="threadTest" class="org.owls.thread.vo.ThreadTest" init-method="init"/>
init is the method name which generated by user in step 2.
Now we run this project Automatically Thread runs.
Controlling Thread is not relavent with Spring, I guess.
It is basically belongs to java rules.
I hope this TIP(?) will be helpful to people who just entered world of programming :-)

Portable Class Library and ObservableCollection, updating UI Thread

I'm not very experienced with this topic so forgive me if this isn't very clear.
I've created a Portable Class Library that has an ObservableCollection of Sections, and each secion has an ObservableCollection of Items.
Both of these collections are bound to the UI of separate Win8 and WP8 apps.
I'm trying to figure out the correct way to populate these collections correctly so that the UI gets updated from the PCL class.
If the class was inside the win8 project I know I could do something like Dispatcher.BeginInvoke, but this doesn't translate to the PCL, nor would I be able to reuse that in the WP8 project.
In this thread (Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync) I discovered the SynchroniationContext class.
I passed in a reference to the main app's SynchroniationContext, and when I populate the sections I can do so because it's only the one object being updated:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
UpdateSections(sections);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post(UpdateSections, sections);
}
However, when I try to do the same thing with articles, I have to have a reference to both the section AND the article, but the Post method only allows me to pass in a single object.
I attempted to use a lambda expression:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
section.Items.Add(item);
}, null);
}
but I'm guessing this is not correct as I'm getting an error about being "marshalled for a different thread".
So where am I going wrong here? how can I update both collections correctly from the PCL so that both apps can also update their UI?
many thanks!
Hard to say without seeing the rest of the code but I doubt is has anything to do with Portable Class Libraries. It would be good to see the details about the exception (type, message and stack trace).
The way you call Post() with more than argument looks correct. What happens if you remove the if check and simply always go through SynchronizationContext.Post()?
BTW: I don't explicitly pass in the SynchronizationContext. I assume that the ViewModel is created on the UI Thread. This allows me to capture it like this:
public class MyViewModel
{
private SynchronizationContext _context = SynchronizationContext.Current;
}
I would recommend that at least in your ViewModels, all publicly observable state changes (ie property change notifications and modifications to ObservableCollections) happen on the UI thread. I’d recommend doing the same thing with your model state changes, but it might make sense to let them make changes on different threads and marshal those changes to the UI thread in your ViewModels.
To do this, of course, you need to be able to switch to the UI thread in portable code. If SynchronizationContext isn’t working for you, then just create your own abstraction for the dispatcher (ie IRunOnUIThread).
The reason you were getting the "marshalled on a different thread" error is that you weren't passing the item to add to the list as the "state" object on the Post(action, state) method.
Your code should look like this:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
var item = (YourItemnType) e;
section.Items.Add(item);
}, item);
}
If you make that change, your code will work fine from a PCL.

Application Object Won't Share

I'm having issues with my Application Object. I am currently using a Service to simulate incoming data from an electronic game board. This data is represented as a 2D boolean array. Every five seconds the Service uses a method of the Application Object to update the array (setDetectionMap()). This array is being read by a Thread in my main Activity using another method (getDetectionMap()). After some debugging I am almost positive that the main Activity is not seeing the changes. Here is the code for my Application Object:
public class ChessApplication extends Application{
private static ChessApplication singleton;
private boolean[][] detectionMap;
public static ChessApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton=this;
detectionMap=new boolean[8][8];
}
public boolean[][] getDetectionMap(){
return detectionMap;
}
public void setDetectionMap(boolean[][] newMap){
detectionMap=newMap;
Log.d("Chess Application","Board Changed");
}
}
I've checked my Manifest, I've rewritten my object declaration a dozen times, I've added LogCat tags to make sure that the code is executing when I think it should be, and I've even implemented the supposedly redundant Singleton code. Any ideas what could be causing this? Incidentally can anyone tell me how to view variable states as the activity is running? Thanks in advance.
Is your Activity calling getDetectionMap() to get the new map after the update occurs?
Because otherwise, it's holding onto a reference to the old boolean[][] array, wheras setDetectionMap(...) isn't actually updating the current data structure, it's just updating the "detectionMap" variable to point to a different one. As such, your main activity won't be aware of the swapout until the next time it calls getDetectionMap.
Easy fix: in setDetectionMap, manually copy values from newMap into detectionMap. Or, update the Activity's reference so it's looking at the right map.
One other observation entirely unrelated to the original question: It's quite unusual to override Application during Android development, and is usually considered a "code smell" unless you have a really good reason for doing so. In this case I imagine it's so that you can communicate between your service and Activity, but you create a middle-man where one isn't entirely necessary. Here's a useful SO thread on how to communicate directly between the two :)

Resources