Can't get instance of CI Object to use model in run() function of thread class.
Thread is starting ok but not able to call model functions Please help !!!
class Clinical extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->helper('directory');
}
public function index()
{
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
ini_set("max_execution_time", '0');
ini_set('memory_limit', '1024M');
$dirList = scandir('../clinicalTrial/');
$data["dirList"] = $dirList;
$this->load->view('clinical',$data);
}
public function import()
{
$folder = $_POST["folder_name"];
$dir = directory_map('../clinicalTrial/'.$folder);
$key = $folder;
$myThreadObj = new ClinicalThread($dir,$key);
var_dump($myThreadObj->start());
echo "Import Done";
exit;
}
}
class ClinicalThread extends Thread
{
public $dir = array();
public $key = "";
public function __construct($dir,$key)
{
$this->dir=$dir;
$this->key=$key;
}
function run()
{
$CI = & get_instance();
echo "";
print_r($CI);
exit;
if(!empty($this->dir))
{
foreach($this->dir as $file)
{
$CI->ct->extract($this->key,$file);
}
}
}
}
You cannot call Model function of the framework inside thread, as It doesn't load the framework engine inside the thread.
Please use direct DB connection inside the thread to communicate with the Database.
Related
I'm trying to get a list of the system users in Vala, but all I get is an empty list. As Vala documentation is quite simple, I dont know how to solve this. This is what I'm trying:
var users_list = Act.UserManager.get_default ().list_users ();
It looks as though the UserManager doesn't have the data available when it is created. The data is only available when the is_loaded property is true.
In GLib a notify signal can be emitted when a property changes. So we will take advantage of that in the following working example:
int main () {
var loop = new EventLoop ();
var manager = new UserManager (loop);
if (!manager.is_running) {
print ("AccountsService is not running\n");
return 1;
}
loop.run ();
return 0;
}
class UserManager {
private Act.UserManager manager;
private EventLoop loop;
public bool is_running {
get { return !manager.no_service (); }
}
public UserManager (EventLoop event_loop) {
loop = event_loop;
manager = Act.UserManager.get_default ();
manager.notify["is-loaded"].connect( this.loaded );
}
void loaded (ParamSpec property) {
print (#"Property \"$(property.name)\" has changed\n");
this.print_users ();
this.loop.quit ();
}
void print_users () {
if (!manager.is_loaded) { return; }
print ("%-20s | %-20s\n", "User name", "Logged In Time");
foreach (var user in manager.list_users ()) {
print ("%-20s | %-20s\n",
user.user_name,
new DateTime.from_unix_local(user.login_time).to_string()
);
}
}
}
class EventLoop {
private MainLoop loop;
public EventLoop () {
loop = new MainLoop ();
}
public void run() {
this.loop.run ();
}
public void quit() {
Idle.add (()=> {
this.loop.quit ();
return Source.REMOVE;
});
}
}
The example creates a UserManager class to wrap the AccountsService UserManager. It is assumed that the user manager is never loaded when it is first returned by Act.UserManager.get_default () so as part of the constructor a callback is set up when the is_loaded property changes. This is the line:
manager.notify["is-loaded"].connect( this.loaded );
The manager has a notify signal that is emitted when any property changes. The example uses a signal detail to only get fired when the is-loaded property changes. For some reason this uses a dash in its name, rather than the underscore. I couldn't find any documentation on why that is. With a notify signal the callback can take a ParamSpec as an argument. This was used to find details of the property that changed, but in the example is no longer necessary because the "is-loaded" signal detail is used.
The example also creates an EventLoop class that acts as a wrapper around GLib's MainLoop. UserManager has EventLoop as a dependency so the event loop can quit and the program finish.
Another approach would be to use the org.freedesktop.Accounts D-Bus service directly from Vala.
I got some questions regarding the use of threads, specially when you have to wait for a thread to be finished so you can perform other operations.
In my app, I use threads for operations such as http connections or when I read from or write to a RecordStore.
For example in the following class that I use to initialize my thread, I retrieve some customers from a webservice using the method called HttpQueryCustomers.
public class thrLoadCustomers implements Runnable {
private RMSCustomer mRMSCustomer;
private String mUrl;
public thrLoadCustomers(RMSCustomer rmsCust, String url) {
mRMSCustomer = rmsCust;
mUrl = url;
}
public void run() {
String jsonResultados = "";
try {
jsonResultados = HttpQueryCustomers();
} catch (IOException ex) {
//How to show a message from here??
} catch (SecurityException se) {
//How to show a message here??
} catch (NullPointerException npe) {
//How to show a message from here??
}
if (!jsonResultados.equals("")) {
try {
mRMSCustomer.save(jsonResultados);
} catch (RecordStoreException ex) {
//How to show a message from here???
}
}
}
public String HttpQueryCustomers() throws IOException,SecurityException,NullPointerException {
StringBuffer stringBuffer = new StringBuffer();
HttpConnection hc = null;
InputStream is = null;
System.out.println(mUrl);
try {
hc = (HttpConnection) Connector.open(mUrl);
if (hc.getResponseCode() == HttpConnection.HTTP_OK) {
is = hc.openInputStream();
int ch;
while ((ch = is.read()) != -1) {
stringBuffer.append((char) ch);
}
}
} finally {
is.close();
hc.close();
}
String jsonData = stringBuffer.toString();
return jsonData.toString();
}
}
Notice in the above class that I pass a parameter called rmsCust of the type RMSCustomer
RMSCustomer is a class that I use to handle all the operations related to RMS:
public class RMSCustomer {
private String mRecordStoreName;
private Customer[] mCustomerList;
public RMSCustomer(String recordStoreName) {
mRecordStoreName = recordStoreName;
}
public Customer[] getCustomers() {
return mCustomerList;
}
public Customer get(int index) {
return mCustomerList[index];
}
public void save(String data) throws RecordStoreException,JSONException,NullPointerException {
RecordStore rs = null;
int idNuevoRegistro;
String stringJSON;
try {
rs = RecordStore.openRecordStore(mRecordStoreName, true);
JSONArray js = new JSONArray(data);
//Set the size of the array
mCustomerList = new Customer[js.length()];
for (int i = 0; i < js.length(); i++) {
JSONObject jsObj = js.getJSONObject(i);
stringJSON = jsObj.toString();
idNuevoRegistro = addRecord(stringJSON, rs);
//Add a new Customer to the array
mCustomerList[i] = initializeCustomer(stringJSON, idNuevoRegistro);
}
} finally {
if (rs != null) {
rs.closeRecordStore();
}
}
}
public int addRecord(String stringJSON, RecordStore rs) throws JSONException,RecordStoreException {
byte[] raw = stringJSON.getBytes();
int idNuevoRegistro = rs.addRecord(raw, 0, raw.length);
return idNuevoRegistro;
}
public Customer initializeCustomer(String stringJSON, int idRecord) throws JSONException {
Customer c = new Customer();
JSONObject jsonObj = new JSONObject(stringJSON);
// Set Customer properties
//...
return c;
}
}
This class is used to show a list of customer and ,as you can see, it extends the List class and receives an array of Customers as a parameter.
public class ListCustomers extends List {
private final Customer[] mData;
public static ListCustomers create(Customer[] data) {
int i = 0;
for (; i < data.length; i++) {
if (data[i] == null) {
break;
}
}
String[] names = new String[i];
for (int j = 0; j < i; j++) {
names[j] = data[j].name;
}
return new ListCustomers(names, data);
}
protected ListCustomers(String names[], Customer[] data) {
super("List of Customer", IMPLICIT, names, null);
mData = data;
}
public Customer getSelectedObject() {
return mData[this.getSelectedIndex()];
}
}
Finally this is how I call the thread from the MIDlet (using all the 3 previous classes) when I want to show a List of Customers:
private void showCustomerList(String url) {
showWaitForm();
if (scrCustomerList == null) {
rmsCustomers = new RMSCustomer("rmsCustomers");
thrLoadCustomers load = new thrLoadCustomers(rmsCustomers, url);
Thread t = new Thread(load);
t.start();
try {
t.join();
} catch (InterruptedException ex) {
}
scrCustomerList = ListCustomers.create(rmsCustomers.getCustomers());
scrCustomerList.addCommand(cmdSelect);
scrCustomerList.addCommand(cmdBack);
scrCustomerList.setCommandListener(this);
}
mDisplay.setCurrent(scrCustomerList);
}
Now here's the problems I have :
The showWaitForm() doesn't work (it sets a form with a Gauge as the
Current form)
I don't know how to show all the exceptions that might be thrown from
within the thrLoadCustomers class.
I don't know whether using t.join() is the best choice
The last question is about something the book I'm reading says :
Threads, in particular, can be a scarce commodity. The MSA
specification requires that an application must be allowed to create
ten threads. Just because you can doesn’t mean you should. In general,
try to use the fewest resources possible so that your application will
run as smoothly as possible
This is the first time a use threads, and in my app I might have up to 10 threads (classes). However, I will only execute once thread at the time, will I be going against what the previous quotation says??
I hope I'm not asking too many questions. Thank you very much for your help.
P.D Much of the code I posted here wouldn't have been possible with the help of Gregor Ophey
Question #1 is about a different problem not related to threading, and for which very little code is shown. I'd suggest you to post a new dedicated question with proper explanation of the issue.
Questions #2 and #3: You could define a wrapper class like this:
public class WSResult {
private boolean success; //true if the WS call went ok, false otherwise
private String errorMessage; //Error message to display if the WS call failed.
private Object result; //Result, only if the WS call succeeded.
private boolean completed = false;
//TODO getter and setters methods here
}
In your screen, you can create an instance of result and wait for it:
WSResult result = new WSResult();
//Start thread here
new Thread(new LoadCustomersTask(result)).start();
//This is old school thread sync.
synchronized(result){
while(!result.isCompleted()){
result.wait();
}
}
//Here the thread has returned, and we can diaplay the error message if any
if(result.isSuccess()){
} else {
//Display result.getErrorMessage()
}
Then your runnable would be like this:
class LoadCustomersTask implements Runnable {
private final WSResult result;
public LoadCustomersTask(WSResult res){
result = res;
}
public void run(){
//Do the WS call
//If it went well
result.setSuccess(true);
result.setResult(jsonResultados);
//Else
result.setSuccess(false);
result.setErrorMessage("Your error message");
//In any case, mark as completed
result.setcompleted(true);
//And notify awaiting threads
synchronized(result){
result.notifyAll();
}
}
}
You can also do it with thread.join, but wait/notify is better because you not making the screen depend on the particular thread where the runnable runs. You can wait/notify on the result instance, as shown, or on the runnable if it is intended for a single use.
Question #4: Yes threads must not be abused, specially in JavaME where programs usually run in single core CPUs with a frecuency in the order of MHz. Try not to have more than 1-3 threads running at the same time. If you really need to, consider using a single thread for running all background tasks (a blocking queue).
I have list that is bound to a view when it loads which works fine. I also have a timer that calls a service to check for any new items to add to the list. The problem occurs when I try and add new items to the list I get a error that it needs to be done on the UI thread.
I am attempting to add the items to an ObservableCollection as Below:
private ObservableCollection<ChatMessageViewModel> _items;
public MyViewModel(IMvxMessenger messenger, IMyService myService) : base (messenger)
{
_myService = myService;
_timer = new Timer(GetLatestItems,null, 1000,10000);
}
public async void GetLatestItems()
{
var newItems = await _myService.GetNewMessages();
if (newItems != null && newItems.Count > 0)
{
foreach (var item in newItems)
{
Items.Add(item);
}
}
}
ObservableCollection/INotifyCollectionChanged must be used synchronously - so you must use it on the UI thread.
Timer uses a ThreadPool thread.
To marshall the call back onto the UI, try something like:
public MyViewModel(IMvxMessenger messenger, IMyService myService) : base (messenger)
{
_myService = myService;
_timer = new Timer(GetLatestItems,null, 1000,10000);
}
public async void GetLatestItems()
{
var newItems = await _myService.GetNewMessages();
InvokeOnMainThread(() => {
if (newItems != null && newItems.Count > 0)
{
foreach (var item in newItems)
{
Items.Add(item);
}
}
});
I have an Xpage page with a single Notes document datasource.
After saving a document I want to (conditionally) trigger an agent. The agent takes some time to process and we don't want the user to have to wait for the result, so it should be executed asynchronously.
I've managed to get it working from client side JS by using an XHR to the agent URL, but I would like to do it server side so I can control the "Next page" better. When using .run() or .runonserver() the client waits till the agent completes.
Any idea how I could trigger an agent (from SSJS) on PostSaveDocument without the client waiting for the result?
Try to look at Thread and Jobs application on OpenNTF.org. There are nice demos of running task in background, check it here
As Martin suggested I used the JobScheduler example on OpenNtf and modified it to suit my needs. Resulting code can be found below. Any comments or improvements are welcome.
import java.security.AccessController;
import java.security.PrivilegedAction;
import lotus.domino.Agent;
import lotus.domino.Database;
import lotus.domino.NotesException;
import lotus.domino.Session;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import com.ibm.domino.xsp.module.nsf.ThreadSessionExecutor;
public class JobRunner {
public static void start(String dbPath, String agentName, String paramDocId) {
synchronized (JobRunner.class) {
runningJob = new ISPJob(dbPath, agentName, paramDocId);
runningJob.addJobChangeListener(new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
System.out.println("Done event");
runningJob = null;
}
});
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
runningJob.schedule();
return null;
}
});
}
}
private static ISPJob runningJob;
private static final class ISPJob extends Job {
private ThreadSessionExecutor<IStatus> executor;
private String docId;
private String dbPath;
private String agentName;
public ISPJob(String paramDbPath, String paramAgentName, String paramDocId) {
super(paramDocId);
this.docId = paramDocId;
this.dbPath = paramDbPath;
this.agentName = paramAgentName;
this.executor = new ThreadSessionExecutor<IStatus>() {
#Override
protected IStatus run(Session session) throws NotesException {
System.out.println("Job started" + docId);
System.out.println(" >> Session created: "
+ session.getUserName() + ", Effective User:"
+ session.getEffectiveUserName());
Database db = session.getDatabase(null,dbPath);
if (db != null) {
try {
if (!db.isOpen()) db.open();
if (db.isOpen()) {
System.out.println(" >> Database opened: "
+ db.getTitle());
Agent agent = db.getAgent(agentName);
try {
System.out.println(" >> Agent Started: " + agent.getName());
agent.run(docId);
System.out.println(" >> Agent Ran: " + agent.getName());
} finally {
agent.recycle();
}
}
} finally {
db.recycle();
}
}
System.out.println("Job completed");
return Status.OK_STATUS;
}
};
}
protected IStatus run(IProgressMonitor monitor) {
try {
return executor.run();
} catch (Exception ex) {
return Status.CANCEL_STATUS;
}
}
};
}
You could use a session bean (so it won't get destroyed) that kicks off an Java thread. Or you could issue in code a server console command. Or you implement a DOTS listener.
This may/may not be an option depending on your application requirements but I am having good success calling function in the onClientLoad event which essentially kicks off the process after the XPage has fully loaded.
I am reading Java Concurrency in Practice and got stuck on this program,where author say it won't cause the deadlock. But if I swap the method arguments then it will cause deadlock.
Obj1 = hash-code =1
Obj2 = hash-code =2
Thread1. transfer(Obj1, Obj2) will get lock on fromAcct and will wait for toAcct lock
Thread2.transfer(Obj2, Obj1) will get lock on toAcct and will wait for fromAcct lock
So basically we ended-up in dead-lock.
My question is how come is the dead-lock is avoided in following code.
public class InduceLockOrder {
private static final Object tieLock = new Object();
public void transferMoney(final Account fromAcct,
final Account toAcct,
final DollarAmount amount)
throws InsufficientFundsException {
class Helper {
public void transfer() throws InsufficientFundsException {
if (fromAcct.getBalance().compareTo(amount) < 0)
throw new InsufficientFundsException();
else {
fromAcct.debit(amount);
toAcct.credit(amount);
}
}
}
int fromHash = System.identityHashCode(fromAcct);
int toHash = System.identityHashCode(toAcct);
if (fromHash < toHash) {
synchronized (fromAcct) {
synchronized (toAcct) {
new Helper().transfer();
}
}
} else if (fromHash > toHash) {
synchronized (toAcct) {
synchronized (fromAcct) {
new Helper().transfer();
}
}
} else {
synchronized (tieLock) {
synchronized (fromAcct) {
synchronized (toAcct) {
new Helper().transfer();
}
}
}
}
}
interface DollarAmount extends Comparable<DollarAmount> {
}
interface Account {
void debit(DollarAmount d);
void credit(DollarAmount d);
DollarAmount getBalance();
int getAcctNo();
}
class InsufficientFundsException extends Exception {
}
}
Your example states that it is in fact correct.
Case 1: Thread1.transfer(Obj1, Obj2)
In this case, fromHash < toHash so the first lock is on the fromAcct param or Obj1 and the second is on the toAcct param or Obj2
Case 2: Thread1.transfer(Obj2, Obj1)
In this case, fromHash > toHash so the first lock is on the toAcct param or Obj1 and the second is on the fromAcct param or Obj2
Lock order is same, so no deadlock occurs.