I have a simple viewPart offering some text fields to enter parameters for a selenium test. After filling out these fields the user may start the test which approx. needs 30-45 minutes to run. I want my GUI to be alive during this test giving users the chance to do other things. I need a progress monitor.
I tried to put the selenium test in a job containing Display.getDefault().asyncExec to run it. But my GUI freezes after some seconds giving the busyindicator. The selenium does not update any other view but the progress monitor.
Is there another way to ensure that the job wont block my GUI?
Best,
Mirco
Everything executed in (a)syncExec is using the display thread and therefore blocking your UI until it returns. I suggest you use Eclipse Jobs. This will use the progress indicator that the workbench already offers out of the box.
I would suggest to split your code into code that updates the UI and the code that executes other business. Execute all of it in a separate thread, and when you need to retrieve or set some action to the UI then use the "Display.getDefault().asyncExec".
Thread thread = new Thread("Testing") {
// some shared members
public void run() {
someBusiness();
// or use syncExec if you need your thread
// to wait for the action to finish
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
// UI stuff here
// data retrieval
// values setting
// actions trigging
// but no business
}
});
someBusiness();
};
thread.start();
Related
I have a workflow that executes a couple of activities. When the activity finish, it returns an Outcome either Done or Cancel, from outside and before running the next activity, I need to check if the previous activity was ok or not, in case not, I need to cancel the workflow. I have this
public class CreateEmployee : IWorkflow
{
public void Build(IWorkflowBuilder builder)
{
builder
.WithDisplayName(this.GetType().Name)
.Then<GetDataById>(x => x.WithDisplayName(x.ActivityType.Name))
.When(OutcomeNames.Cancel).Finish()
.Then<InsertEmployee>(x => x.WithDisplayName(x.ActivityType.Name))
.When(OutcomeNames.Cancel).Finish()
.Then<InsertMapping>(x => x.WithDisplayName(x.ActivityType.Name))
.When(OutcomeNames.Cancel).Finish();
}
}
For example, after executing activity GetDataById, if the return is "Cancel", I call Finish(), is this going to stop just the activity and continue the workflow or the workflow will stop completely? I'm not able to test it because I'm using DI and I need to prepare the whole unit test, because I didn't find anything directly related to cancel the whole workflow
I'm not sure if I have fully understood your question, but in the documentation about finish activity it's stated that:
when this activity is used within a workflow, the workflow instance
will enter the Finished state. When used in a child composite
activity, that activity will stop execution and yield back control to
its container. However, it will not stop workflow execution itself.
We have a button in the UI, which, when pressed, will make some remote network call in its own coroutine. However, if the user spams the button for whatever reason, it is possible that the remote data might somehow get corrupted. We would like to prevent this by discarding all requests until the current one is completed.
There are many ways to do this. I have create a simple extension function on CoroutineScope to only launch if the CoroutineScope is not active. This is what I have created:
Extension Function
fun CoroutineScope.safeLaunch(dispatcher: CoroutineDispatcher, block: () -> Unit): Job {
return if (!isActive) {
launch(dispatcher) {
block()
}
} else {
launch {}
}
}
Example Use
fun loadNotifications() {
viewModelScope.safeLaunch(IO) {
getNotifications.invoke() // Suspend function invoke should only be from a coroutine or another suspend function
}
}
The problem is, the above won't compile as I get an error saying
Suspend function invoke should only be from a coroutine or another
suspend function
Does anyone know what I'm doing wrong or how to make it work?
There are multiple problems with this code:
Fixing the error you mentioned is very easy and requires to only specify block as suspendable: block: suspend () -> Unit.
isActive doesn't mean the job/scope is actively running something, but that it hasn't finished. isActive in your example always returns true, even before launching any coroutine on it.
If your server can't handle concurrent actions, then you should really fix this on server side. Limiting the client isn't a proper fix as it can be still exploited by users. Also, you need to remember that multiple clients can perform the same action at the same time.
As you mentioned, there are several ways how this situation can be handled on the client side:
In the case of UI and the button, it is probably the best for the user experience to disable the button or overlay the screen/button with a loading indicator. It gives the user the feedback that the operation is running in the background and at the same time it fixes the problem with multiple calls to the server.
In general case, if we just need to limit concurrency and reject any additional tasks while the last one is still running, probably the easiest is to use Mutex:
private val scope = CoroutineScope(EmptyCoroutineContext)
private val mutex = Mutex()
fun safeLaunch(block: suspend () -> Unit) {
if (!mutex.tryLock()) {
return
}
scope.launch {
try {
block()
} finally {
mutex.unlock()
}
}
}
Note we need a separate mutex per scope or per the type of the task. I don't think it is possible to create such utility as a generic extension function, working with any coroutine scope. Actually, we can implement it in a very similar way to your original code, but by looking at the current job's children. Still, I consider such solution hacking and I discourage it.
My team have developed a new Android app which makes extensive use of Room.
I am unsure whether we are using AsyncTask correctly.
We have had to wrap all calls to insert/update/delete in AsyncTasks which results in a huge number of AsyncTasks. All the calls into Room are from background services. There is no direct Room access from activities or fragments - they get everything via LiveData.
An example call to insert a row:
AsyncTask.execute(() -> myModelDAO.insertInstance(myModel));
With this in the DAO:
#Insert
void insertInstance(MyModel model);
To complete #CommonsWare answer, you can use the Executor class to execute Room queries into a background thread.
Executor myExecutor = Executors.newSingleThreadExecutor();
myExecutor.execute(() -> {
myModelDAO.insertInstance(myModel)
});
Google showed an example on their Android Architecture Components guide.
All the calls into Room are from background services
Then you should not be using AsyncTask. AsyncTask is only for when you want to do work on the main application thread after doing background work, and that is almost never the case with a service. Use something else (thread, thread pool, RxJava, etc.). This has nothing specific to do with Room.
AsyncTask.execute(() -> myModelDAO.insertInstance(myModel));
Looking like incorrect you can use Simple Thread/Threadpool/Schedulers etc
You can use a callback like Consumer<List<object>>callback.
For example:
roomManger.getAllUsertById(user.getId(), this, new Consumer<List<User>>() {
#Override
public void accept(List<Product> listOfUser) {
users.addAll(listOfUser)}
I am develping an app which load some url, parse them, keep them into sqlite db and the UI will read the saved data and show them in controls. This progress should be done in almost an infinit loop. For having fast response i plan to read the data from db in main thread and have an other thread (background worker) to load the data and insert it into db. Is it logical and possible to run read and write process in dispatchertimer, one timer in main thread and the other inside the background worker? and how? Or does anyone have better idea?
main thread:
DispatcherTimer _Timer1 = new DispatcherTimer();
_Timer1.Interval = _Interval;
_Timer1.Tick += _Timer1_Tick;
void _Timer1_Tick(object sender, EventArgs e)
{
// read data from db and show in controls
}
secondary thread:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
DispatcherTimer _Timer2 = new DispatcherTimer();
_Timer2.Interval = _Interval;
_Timer2.Tick += _Timer2_Tick;
}
void _Timer2_Tick(object sender, EventArgs e)
{
// write data into db
}
}
What you're planning to do wont work.
Both your _Timer1_Tick and _Timer2_Tick will run in the UI thread. If you perform some long-running operations there, it'll hang the UI.
I don't get it, why do you need timers at all? Using timers for anything else but measuring time intervals is rarely a good strategy. You could e.g. run your update process in the infinite loop in background, as soon as it put new data in the DB you call Dispatcher.BeginInvoke (passing any data you want) to notify your UI thread it should update itself with the newly available data.
And by the way, for the tasks like "send HTTP request, wait response, parse, store, repeat", the new async/await feature is a natural choice. For WP7 the functionality is available as "Async CTP" redistributable package for Visual Studio 2010, for WP8 it's already integrated into the framework. There're some compatibility issues between the 2, though.
load some url, parse them, keep them into sqlite db and the UI will read the saved data and show them in controls
Please don't do that. Don't create your own thread management system, just don't. I'm not saying it won't work, but it'll most likely backfire in the most horrendous and inexplicable ways. Like for example using a DisptacherTImer completely exploding in your face since it runs on the UI thread. If you really want to use threading considering ThreadPool.QueueUserWorkItem() or Task.Run() to start fire-and-forget actions.
Your workflow is also just strange, I don't get why you need to write data you already have to a DB, then read it back and only then use it. Won't it make more sense to use the deserialized data to sequentially write it to the DB and present it to the UI? Instead of doing the needless loop of involving Disk I/O considering you already have the data?
Have you considered using Messaging in your app? It's a pretty well known MVVM pattern implemented both in MVVM Light as the Messenger class and in PRISM as the EventAggregator. It seems to me that your system has a Message for "new data available from service" and that message has two subscribers: writing to a DB and updating the UI.
We are trying to develop a small application that can monitor the programs/processes that are executing in a windows machine.
If the program/process is not supposed to run, it should be blocked. It works similar to an antivirus.
This is the basic idea.
I want to know the ways to hook into the OS to get notified about every single program/process trying to run in the machine.
The easiest way is to use WMI. Specifically monitor the Win32_ProcessStartTrace. This is better than Win32_Process, because it is setup to use events whereas Win32_Process requires polling which is more CPU intensive. Below is how to do it in C#. First make sure that System.Management is setup as a reference for your project.
public System.Management.ManagementEventWatcher mgmtWtch;
public Form1()
{
InitializeComponent();
mgmtWtch = new System.Management.ManagementEventWatcher("Select * From Win32_ProcessStartTrace");
mgmtWtch.EventArrived += new System.Management.EventArrivedEventHandler(mgmtWtch_EventArrived);
mgmtWtch.Start();
}
void mgmtWtch_EventArrived(object sender, System.Management.EventArrivedEventArgs e)
{
MessageBox.Show((string)e.NewEvent["ProcessName"]);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
mgmtWtch.Stop();
}
The code will generate a messagebox everytime you launch a new process. From there you can check a whitelist/blacklist and act appropriately.
I havn't tried geting real-time notification. How ever, Here is how to get running processes in C#
using System.Diagnostics;
//Somewhere in your method
Process[] runningList = Process.GetProcesses();
foreach(Process p in runningList){
Console.WriteLine("Process: {0} ID: {1}", p.ProcessName, p.Id);
}
You can also use the following props of a process
StartTime - Shows the time the process started
TotalProcessorTime - Shows the amount of CPU time the process has taken
Threads - gives access to the collection of threads in the process
I would check up the Win32-api SetWindowsHookEx with the constant WH_GETMESSAGE to add a callback to your program when a new window is being created.
http://pinvoke.net/default.aspx/user32.SetWindowsHookEx
Google that API and WH_GETMESSAGE to find out more.
Also check out the following articles/code librarys:
http://www.vbaccelerator.com/home/Vb/Code/Libraries/Hooks/vbAccelerator_Hook_Library/article.asp
http://www.codeproject.com/KB/DLL/hooks.aspx?fid=2061&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=76&select=726975