How to send data to the main isolate from workmananger's isolate? - flutter

My problem is that flutter Hive cannot be opened from multiple isolates. So I want the data fetched in workmananger task to be sent to the main isolate where the hive box is opened and modify it there to avoid corrupting it. I should take into consideration when the app is alive and when it is not => for example when the app is not alive, I edit the hive file directly since it will be only opened in the workmanager isolate whereas if the app is not alive I send the data to the main isolate and edit the hive file. My problem is that I do not know how to track lifecycle within the workmanager task and I do not know how to send the data to the main isolate. Any workarounds or solutions for the problem or how to code the above?

After some research the solution is as follows:
First you register a port on the initialization of the main isolate like this:
void listenToUpdatesFromWorkManager(String name) { var port = ReceivePort(); IsolateNameServer.registerPortWithName(port.sendPort, name); }
You give it a unique name in order to identify it from any other opened isolates like this:
SendPort sendPort = IsolateNameServer.lookupPortByName(name);

Related

How to prevent Gtk g_source_timeout_add from triggering in multiple instances

I register a timeout with:
timeout_tag = g_timeout_add(250, update_time, NULL);
and destroys it with
g_source_remove(timeout_tag);
But as I open multiple instances of the same app, the timeout triggers update_time in all instances instead of just one. How would I isolate them?
I'm creating a new application with
app = gtk_application_new("com.lunacd.reminder", G_APPLICATION_FLAGS_NONE);
Should I generate a uuid and append it to com.lunacd.reminder so that the identifier remains distinct?
As #jcoppens pointed out, timeouts are triggered independently. This question is invalid.

Background Process as NSOperation or Thread to monitor and update File

I want to check if a pdf file is changed or not, and if is changed i want to update the corresponding view. I don't know if it's more suitable to use a background process as a Thread or as an NSOperation to do this task. The Apple Documentation says: "Examples of tasks that lend themselves well to NSOperation include network requests, image resizing, text processing, or any other repeatable, structured, long-running task that produces associated state or data.But simply wrapping computation into an object doesn’t do much without a little oversight".
Also, if I understood correctly from the documentation, a Thread once started can't be stopped during his execution while an NSOperation could be paused or stopped and also they could rely on dependency to wait the completion of another task.
The workflow of this task should be more or less this diagram:
Task workflow
I managed to get the handler working after the notification of type .write has been sent. If i monitor for example a *.txt file everything works as expected and i receive only one notification. But i am monitoring a pdf file which is generated from terminal by pdflatex and thus i receive with '.write' nearly 15 notification. If i change to '.attrib' i get 3 notification. I need the handler to be called only once, not 15 or 3 times. Do you have any idea how can i do it or is not possible with a Dispatch Source? Maybe there is a way to execute a dispatchWorkItem only once?
I have tried to implement it like this(This is inside a FileMonitor class):
func startMonitoring()
{
....
let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: fileStringURL)
let fileDescriptor = open(fileSystemRepresentation, O_EVTONLY)
let newfileMonitorSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor,
eventMask: .attrib,
queue: queue)
newfileMonitorSource.setEventHandler(handler:
{
self.queue.async
{
print(" \n received first write event, removing handler..." )
self.newfileMonitorSource.setEventHandler(handler: nil)
self.test()
}
})
self.fileMonitorSource = newfileMonitorSource
fileMonitorSource!.resume()
}
func test()
{
fileMonitorSource?.cancel()
print(" restart monitoring ")
startMonitoring()
}
I have tried to reassign the handler in test(), but it's not working(if a regenerate the pdf file, what is inside the new handler it's not executed) and to me, doing in this way, it seems a bit boilerplate code. I have also tried the following things:
suspend the DispatchSource in the setEventHandler of startMonitoring() (passing nil), but then when i am resuming it, i get the remaining .write events.
cancel the DispatchSource object and recall the startMonitoring() as you can see in the code above, but in this way i create and destroy the DispatchSource object everytime i receive an event, which i don't like because the cancel() function shoul be called in my case only when the user decide to disable this feauture i am implementing.
I will try to write better how the workflow of the app should be so you can have an more clear idea of what i am doing:
When the app starts, a functions sets the default value of some checkboxes of the window preference. The user can modify this checkboxes. So when the user open a pdf file, the idea is to launch in a background thread the following task:
I create a new queue call it A and launch asynch an infinite while where i check the value of the UserDefault checkboxe (that i use to reload and update the pdf file) and two things could happen
if the user set the value to off and the pdf document has been loaded there could be two situations:
if there is no current monitoring of the file (when the app starts): continue to check the checkboxe value
if there is currently a monitoring of the file: stop it
if the user set value to on and the pdf document has been loaded in this background thread (the same queue A) i will create a class Monitor (that could be a subclass of NSThread or a class that uses DispatchSourceFileSystemObject like above), then i will call startMonitoring() that will check the date or .write events and when there is a change it will call the handler. Basically this handler should recall the main thread (the main queue) and check if the file can be loaded or is corrupted and if so update the view.
Note: The infinite while loop(that should be running in the background), that check the UserDefault related to the feature i am implementing it's launched when the user open the pdf file.
Because of the problem above (multiple handlers calls), i should use the cancel() function when the user set checkboxe to off, and not create/destroy the DispatchSource object everytime i receive a .write event.

Multiple services using Firebase job dispatcher in android

For an android app, i want start three services using firebase job dispatcher on different days. Can I use same FirebaseDispatcher object for all the three jobs?. Meanwhile, How to maintain same FirebaseDispatcher object even though app is closed?. If i use static object it will be cleared if app crashes. So how to maintain my FirebaseDispatcher object for scheduling multiple services using same dispatcher object? or Can I create different FirebaseDispatcher object for different services? Is it good practice?
You can use the same FirebaseJobDispatcher for all Jobs.
When the application is closed, your Jobs will be executed. How? This is the Android OS concern.
You simply describe when and how your Jobs will be launched. It's all. Read the documentation again and see the comments in the source code of the library.
You can create the new FirebaseJobDispatcher for different Jobs.
Misapplication of static objects -- is bad practice.
So
FirebaseJobDispatcher dispatcher1 =
new FirebaseJobDispatcher(new GooglePlayDriver(context));
Job job1 = dispatcher1.newJobBuilder()
.setService(YourService1.class)
.setTag(Const.JOB_TAG_1)
// more options to run
.build();
Job job2 = dispatcher1.newJobBuilder()
.setService(YourService2.class)
.setTag(Const.JOB_TAG_2)
// ...
.build();
dispatcher1.mustSchedule(job1);
FirebaseJobDispatcher dispatcher2 =
new FirebaseJobDispatcher(new GooglePlayDriver(context));
dispatcher2.mustSchedule(job2);
dispatcher1.cancel(Const.JOB_TAG_1);
dispatcher2.cancel(Const.JOB_TAG_2);

How to get application process to wait until the socket has data to read using libevent bufferevents?

I'm working with libevent for the first time and have been having an issue trying to get my application to not run until the read callback is called. I am using bufferevents as well. Essentially I am doing is trying to avoid the sleep in my main application loop and instead have the OS wake up the process (via libevent) when there is data to be read off the socket. Anyone know how to do this? I found in an alpha build of libevent that you can set a base event loop to be EVLOOP_NO_EXIT_ON_EMPTY, but from looking at the libevent code that will just use up my whole proc I believe. I also read on this question that it is a bad idea to set a socket to blocking on windows which is why I haven't done that as a solution either. I will mark this with libuv and libev too since they are similar and might contribute to my solution.
you have to use the following api, some of the API may be oudated you can search google for new one.
struct event_base *base ;
struct event g_eve
base = event_init();
//after binding the socket register your socket for read event using below api
event_set(&g_eve, SockFd, EV_READ | EV_PERSIST, CallbackFunctin, &g_eve);
event_add(&g_eve, NULL);
event_base_dispatch(base);

WMI and Win32_DeviceChangeEvent - Wrong event type returned?

I am trying to register to a "Device added/ Device removed" event using WMI. When I say device - I mean something in the lines of a Disk-On-Key or any other device that has files on it which I can access...
I am registering to the event, and the event is raised, but the EventType propery is different from the one I am expecting to see.
The documentation (MSDN) states : 1- config change, 2- Device added, 3-Device removed 4- Docking. For some reason I always get a value of 1.
Any ideas ?
Here's sample code :
public class WMIReceiveEvent
{
public WMIReceiveEvent()
{
try
{
WqlEventQuery query = new WqlEventQuery(
"SELECT * FROM Win32_DeviceChangeEvent");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
Console.WriteLine("Waiting for an event...");
watcher.EventArrived +=
new EventArrivedEventHandler(
HandleEvent);
// Start listening for events
watcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(10000);
// Stop listening for events
watcher.Stop();
return;
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while trying to receive an event: " + err.Message);
}
}
private void HandleEvent(object sender,
EventArrivedEventArgs e)
{
Console.WriteLine(e.NewEvent.GetPropertyValue["EventType"]);
}
public static void Main()
{
WMIReceiveEvent receiveEvent = new WMIReceiveEvent();
return;
}
}
Well, I couldn't find the code. Tried on my old RAC account, nothing. Nothing in my old backups. Go figure. But I tried to work out how I did it, and I think this is the correct sequence (I based a lot of it on this article):
Get all drive letters and cache
them.
Wait for the WM_DEVICECHANGE
message, and start a timer with a
timeout of 1 second (this is done to
avoid a lot of spurious
WM_DEVICECHANGE messages that start
as start as soon as you insert the
USB key/other device and only end
when the drive is "settled").
Compare the drive letters with the
old cache and detect the new ones.
Get device information for those.
I know there are other methods, but that proved to be the only one that would work consistently in different versions of windows, and we needed that as my client used the ActiveX control on a webpage that uploaded images from any kind of device you inserted (I think they produced some kind of printing kiosk).
Oh! Yup, I've been through that, but using the raw Windows API calls some time ago, while developing an ActiveX control that detected the insertion of any kind of media. I'll try to unearth the code from my backups and see if I can tell you how I solved it. I'll subscribe to the RSS just in case somebody gets there first.
Well,
u can try win32_logical disk class and bind it to the __Instancecreationevent.
You can easily get the required info
I tried this on my system and I eventually get the right code. It just takes a while. I get a dozen or so events, and one of them is the device connect code.