GTK# Application.Invoke Not Working - c#

I'm working on an application that has been tightly bound to GTK# by using Application.Invoke's through many of it's libraries. Unfortunately, we're porting the application (server type application) to a system with no window manager, so it currently crashed when we initialize GTK.
Application.Invoke doesn't seem to work without calling Application.Init, even when running my own GLib.MainLoop.
I am looking for a suitable replacement for Application.Invoke. How should I go about replacing Application.Invoke within the Libraries used by the application, so that I can remove the dependency on GTK ?
Note: I've proposed a refactoring to get rid of the GUI from the app and domain code and move it into a view, but that's been shot down for now. I'm basically trying to get it to run on a system with no window manager.

If it's async processing you want that doesn't need to happen on a specific thread, have a look at System.Threading.ThreadPool.QueueUserWorkItem. The main problem about this approach is that you have to ensure thread safety yourself.
If you do need it to happen on the main thread, you'll need to create a list of delegates to invoke and poll that list periodically on the main thread (or wait for something to be posted to it):
using System.Collections.Generic;
using System.Threading;
class Main {
Queue<Action> actions = new Queue<Action> ();
ManualResetEvent the_event = new ManualResetEvent (false);
public void Invoke (Action action)
{
lock (actions) {
actions.Enqueue (action);
the_event.Set ();
}
}
public void Poll ()
{
Action action = null;
lock (actions) {
if (actions.Count > 0) {
action = actions.Dequeue ();
}
}
if (action != null)
action ();
}
public void Wait ()
{
Action action = null;
while (true) {
the_event.WaitOne ();
lock (actions) {
if (actions.Count > 0) {
action = actions.Dequeue ();
} else {
the_event.Reset ();
}
}
if (action != null)
action ();
}
}
}

Application.Invoke basically works by keeping a list of delegates to run.
Each time the GTK main loop iterates it checks this list and executes anything it finds. It sounds like you need a background thread that loops like this.
That said, I can't imagine how or why you need this looped invoke on a non-graphical app, you would probably be just as well served by simply calling directly there and then. Eg:
public static class Application {
public static void Invoke ( EventHandler dothis ) {
if ( dothis != null ){
dothis( null, null ); }
}
}

Application.Invoke does not need to be replaced (at least for the version I am using). This was a misconception. Application.Inoke simply turns around and adds a delegate to GLib.Timeout, with the timeout set to 0, and returns "false", therefore only firing once.
Instead of getting rid of Application.Invoke, I attempted to find out why my delegates were not firing when using Application.Invoke without Appliation.Run or Application.Init. Keep in mind that I had already started my own GLib.MainLoop.
As it turns out, the Application's static constructor calls GLib.Thread.Init(), which is basically a timebomb. GLib's documentation states that GLib.Thread.Init must be called when using multiple threads, and that if GLib.Thread.Init is ever called, it must be called BEFORE any other GLib usage.
So, in the code I was working with, we added a delegate to GLib.Timeout after Application.Init, but before Application.Run, and before any calls to Application.Invoke. This means we were safe, because Application.Init would invoke the static constructor of Application, therefore invoking GLib.Thread.Init. This was good. However, when we removed Application.Init, and called Timeout.Add first, Thread.Init had not yet been called. This meant that if we called Thread.Init later, the threading, timeouts, delegates, etc, would choke.
Sure enough, Application.Invoke or Application.Run would invoke the static constructor of Application, which in turn would invoke GLib.Thread.Init. This caused the problem.
TLDR;
Long story short, make sure you invoke Application's static constructor before using Timeout.Add in your application code. Don't call Glib.Thread.Init manually, because calling it twice on Mono will make the application crash.
This is okay:
Application.Init();
Timeout.Add(0, delegate { return false; });
Application.Invoke(delegate { Console.WriteLine("Hey"); });
Application.Run();
This will ruin your life:
// Application.Init();
Timeout.Add(1000, delegate { return false; });
Application.Invoke(delegate { Console.WriteLine("Hey"); });
new MainLoop().Run();
//Application.Run();
But this is fine:
// Application.Init();
Application.Invoke(delegate {});
Timeout.Add(1000, delegate { return false; });
Application.Invoke(delegate { Console.WriteLine("Hey"); });
new MainLoop().Run();
//Application.Run();

Related

Declaring Thread in a Constructor in C#

I´m currently figuring out threads and how to work with them.
At the same time Im working on my understanding on Events/Global Events (just for context).
I defined a thread inside a object with the function the thread will use on thread.Start().
internal class Name
{
private Thread testthread;
private EventWaitHandle globalEvent;
private Eventstest evente = new Eventstest(); //Just to add some methods
public Name(Thread testthread, EventWaitHandle globalEvent)
{
this.testthread = testthread;
this.globalEvent = globalEvent;
}
public void Execute()
{
bool terminate = false;
bool eventset = false;
bool rdy = false;
while (!terminate)
{
if (evente.CheckSysEvent(globalEvent))
{
eventset = true; //This is just to check with debugger if the event was raised elsewhere
}
Thread.Sleep(100);
}
}
}
So now, like in this example in a Windows Forms App, Im trying to set an instance of this class while setting the instance of the thread at the same time (with the work method the should run later on).
Im struggling with this part here.
private void btn_runThread_Click(object sender, EventArgs e)
{
threadClass = new Name(new Thread(ProblemHere), globalEvent);
threadClass.Execute();
}
This is a button which starts the thread with the work its supposed to do.
The variable threadClass is just the initialization in the forms1.cs:
Name threadClass;
I know that it wants a delegate to pass the method which the thread should use on start.
I tried pretty much anything I found and cant make it work.
I cant just pass the method, that doesnt work.
And the stuff I found in the c# documentation is pretty much just passing the method, as far as I understood it.
Which is propably wrong.
And I just noticed, how am I able to actually call on that property/thread.start if its only created on runtime?
Not a full solution, but a bump to get you going:
What I would suggest is a little refactor like this
internal class Name
{
private Thread testthread;
private EventWaitHandle globalEvent;
private Eventstest evente = new Eventstest(); //Just to add some methods
public Name(EventWaitHandle globalEvent)
{
this.testthread = new Thread(Execute); // Creates a Thread, that is directed to execute `Execute`
this.globalEvent = globalEvent;
this.testthread.Start(); // Tells the framework to schedule the thread for execution.
}
private void Execute()
{
bool terminate = false;
bool eventset = false;
bool rdy = false;
while (!terminate)
{
if (evente.CheckSysEvent(globalEvent))
{
eventset = true; //This is just to check with debugger if the event was raised elsewhere
}
Thread.Sleep(100);
}
}
}
And in the Button handler just do
private void btn_runThread_Click(object sender, EventArgs e)
{
threadClass = new Name(globalEvent);
}
Mind that there are still a good portion of mistakes and ooopsies, but at least, this will keep your GUI thread running and you may gain an understanding to go on from here.
A totally different approach (if you are willing to consider it) would be to use a System.Windows.Forms.Timer instead. With that you can have a method called every X time, which would check the state of the globalevent as you are trying to get the thread to doing. The timer, however, makes this a little more convenient.
The typical way would be to create the thread in the constructor, as described in the answer by Fildor.
But I want to point out that using the Thread object directly is rarely the correct way to do things since there are other tools more suited for whatever you are tryibng to do:
If you want to do something compute heavy on a background thread once, and update the UI after it has been done. Use Task.Run and async/await
If you want to do something every X seconds. Use a timer. There are both timers that run on the main thread or a background thread, see differences between timers.
If you want to run an compute heavy operation in parallel, use Parallel.For, possibly in combination with Task.Run.
If you want to call IO intensive methods without freezing the UI, use async/await in combination with the appropriate Async methods.
If you want to create a producer/consumer or other processing pipeline there is the DataFlow library

InvokeRequired=true but BeginInvoke fails causing freeze

C# windows forms VS 2013 OS:Win7
I am having an interesting problem where invokeRequired is true but when I call beginInvoke() it never executes and the window never closes.
However when I remove beingInvoke() altogether the window closes ok.
public void CloseMyForm()
{
//if I remove this if block altogether including beingInvoke() the window closes ok
if ( !this.IsDisposed && this.InvokeRequired && this.IsHandleCreated )
{
log("callin begininvoke()"); //this is logged correctly
this.BeginInvoke((MethodInvoker)delegate() { CloseMyForm(); });
return;
}
log("outside of begin invoke"); //this is never logged
this.Close();
}
CloseMyForm is called by a separate thread which is created like this at the startup. Please note this is not the main window but a separate window open from the main form.
Thread connectThread = new Thread(new ThreadStart(CheckWhenToCloseMyForm));
public void CheckWhenToCloseMyForm()
{
while (true)
{
CallSomeFunc();
CallSomeFunc1();
if (allconditionsmet)
{
System.Threading.Thread.Sleep(1000);
CloseMyForm();
break;
}
}
}
The BeginInvoke is made available via the base Control class.
Executes a delegate asynchronously on the thread that the control's underlying handle was created on
If the InvokedRequired property is actually true, that means "the caller must call an invoke method when making method calls to the control because the caller is on a different thread than the one the control was created on".
It looks like you're incorrectly calling BeginInvoke, you should try calling Invoke instead.
Executes the specified delegate on the thread that owns the control's underlying window handle
public void CloseMyForm()
{
if (!this.IsDisposed && this.InvokeRequired && this.IsHandleCreated)
{
log("calling invoke()");
this.Invoke((MethodInvoker)delegate() { CloseMyForm(); });
}
else
{
log("outside of invoke"); // this is never logged
this.Close();
}
}
Check out this neat little extension method that could help simplify this. With this you could write your close method like this instead.
public void CloseMyForm()
{
this.ThreadSafeInvoke(() => this.Close());
}
Okay, now that you have provided this snippet I understand the issue.
Thread connectThread = new Thread(new ThreadStart(CheckWhenToCloseMyForm));
public void CheckWhenToCloseMyForm()
{
while (true)
{
CallSomeFunc();
CallSomeFunc1();
if (allconditionsmet)
{
System.Threading.Thread.Sleep(1000);
CloseMyForm()
}
}
}
In your while loop you need to break or return after you invoke CloseMyForm. That's it...very simple. You can use either BeginInvoke or Invoke.

Reentrant Timer in Windows Service

I want to build a windows Service, which should execute different methods at different times. Its not about accuracy at all.
Im using a system.timers.timer, and regulate the different methods to be executed within the Eventhandler-method with counters. Thats working allright that far.
All of the methods are accessing a COM-port, making it neccessary to grant acceess-rights to only one method at a time. But since the methods can take some time to finish, the timer might tick again and want to execute another method while the COM-port is still being occupied. In this case, the event can and should just be dismissed.
Simplified down to one method, my elapsedEventHandler-method looks something like the following (try-catch and the different methods excluded here)
Note: While this is running perfectly on my Win7 x64, it struggles on a Win7 x86 machine with pretty much the very same software installed, whenever the method to be executed takes a long time. The timer wont tick any more, no Exception is thrown. Nothing! my question now is: Am I doing the part with access-control and the timer right, so that i can focus on other things? Im just not that familiar with timers and especially threading
private static int m_synchPoint=0;
private System.Timers.Timer timerForData = null;
public MyNewService()
{
timerForData = new System.Timers.Timer();
timerForData.Interval = 3000;
timerForData.Elapsed += new ElapsedEventHandler(Timer_tick);
}
//Initialize all the timers, and start them
protected override void OnStart(string[] args)
{
timerForData.AutoReset = true;
timerForData.Enabled = true;
timerForData.Start();
}
//Event-handled method
private void Timer_tick(object sender, System.Timers.ElapsedEventArgs e)
{
////safe to perform event - no other thread is running the event?
if (System.Threading.Interlocked.CompareExchange(ref m_synchPoint, 1, 0) == 0)
{
//via different else-ifs basically always this is happening here, except switching aMethod,bMethod...
processedevent++;
Thread workerThread = new Thread(aMethod);
workerThread.Start();
workerThread.Join();
m_synchPoint=0;
}
else
{
//Just dismiss the event
skippedevent++;
}
}
Thank you very much in advance!
Any help is greatly appreciated!
I would recommend using System.Threading.Timer for this functionality. You can disable the timer when it executes, process your data, then re-enable the timer.
EDIT:
I think it makes more sense to use System.Threading.Timer because there isn't really a reason you need to drop the timer on a design surface, which is pretty much the only reason to use System.Timers.Timer. I really wish MS would remove it anyways, it's wrapping System.Threading.Timer which isn't all that difficult to use in the first place.
Yes, you do risk a problem with re-entrancy which is why I specified to change the timeout toTimeout.Infinite. You won't have this re-entrancy problem if you construct the timer with Timeout.Infinite.
public class MyClass
{
private System.Threading.Timer _MyTimer;
public MyClass()
{
_MyTimer = new Timer(OnElapsed, null, 0, Timeout.Infinite);
}
public void OnElapsed(object state)
{
_MyTimer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("I'm working");
_MyTimer.Change(1000, Timeout.Infinite);
}
}
If you want just skip method invocation while previous method didn't finish just use Monitor.TryEnter(lockObject) before calling your method.
EDIT:
Here's an example -
public class OneCallAtATimeClass
{
private object syncObject;
public TimerExample()
{
syncObject = new object();
}
public void CalledFromTimer()
{
if (Monitor.TryEnter(syncObject);)
{
try
{
InternalImplementation();
}
finally
{
Monitor.Exit(syncObject);
}
}
}
private void InternalImplementation()
{
//Do some logic here
}
}
You can try this:
When the timer fires, disable the timer.
When the task is complete, re-enable the timer...possibly in the Finally clause.
You correctly use CompareExchange to test and set the m_synchPoint field when doing the initial check. You incorrectly use direct assignment to reset the value to 0 at the end of the method. You should use Interlocked.Exchange instead to reset the value to 0. As a side note, you should also change m_synchPoint to an instance field -- it should not be static.

UI Thread .Invoke() causing handle leak?

In what circumstances would updating a UI control from a non-UI thread could cause the processes' handles to continually increase, when using a delegate and .InvokeRequired?
For example:
public delegate void DelegateUIUpdate();
private void UIUpdate()
{
if (someControl.InvokeRequired)
{
someControl.Invoke(new DelegateUIUpdate(UIUpdate));
return;
}
// do something with someControl
}
When this is called in a loop or on timer intervals, the handles for the program consistently increase.
EDIT:
If the above is commented out and amended as such:
public delegate void DelegateUIUpdate();
private void UIUpdate()
{
//if (someControl.InvokeRequired)
//{
// someControl.Invoke(new DelegateUIUpdate(UIUpdate));
// return;
//}
CheckForIllegalCrossThreadCalls = false;
// do something with someControl
}
...then the handles stop incrementing, however I don't want to allow cross thread calls, of course.
EDIT 2:
Here is a sample that shows the handles increase:
Thread thread;
private delegate void UpdateGUI();
bool UpdateTheGui = false;
public Form1()
{
InitializeComponent();
thread = new Thread(new ThreadStart(MyThreadLoop));
thread.Start();
}
private void MyThreadLoop()
{
while (true)
{
Thread.Sleep(500);
if (UpdateTheGui)
{
UpdateTheGui = false;
UpdateTheGuiNow();
}
}
}
private void UpdateTheGuiNow()
{
if (label1.InvokeRequired)
{
label1.Invoke(new UpdateGUI(UpdateTheGuiNow));
return;
}
label1.Text = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss");
label2.Text = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss");
label3.Text = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss");
}
private void btnInvoke_Click(object sender, EventArgs e)
{
UpdateTheGui = true;
}
I had the same problem with
this.Invoke(new DelegateClockUpdate(ChangeClock), sender, e);
creating one handle each call.
The handle increments because Invoke is Synchronous and effectively the handle has been left hanging.
Either a Wait Handle should be used to process the result or the Asynchronous BeginInvoke method as shown below.
this.BeginInvoke(new DelegateClockUpdate(ChangeClock), sender, e);
The Control.Invoke() method doesn't consume any handles. However, this code is clearly called from a thread. A Thread does consume handles, 5 of them.
The Thread class doesn't have a Dispose() method, although it ought to have one. That was probably by design, it would be very difficult to call reliably, impossibly so for threadpool threads. The 5 handles that a thread requires are released by the finalizer. Your program will require ever increasing amounts of handles if the finalizer never runs.
Not getting the finalizer to run is quite unusual. You would have to have a program that starts a lot of threads but doesn't allocate a lot of memory. This tends to only happen in static tests. You can diagnose this condition with Perfmon.exe, use the .NET memory performance counters and check if gen #0 collections are being done.
If this happens in a production program then you'll have to call GC.Collect() yourself to avoid a runaway handle leak.
I've seen the same thing in my code. I fixed it by replacing Invoke with BeginInvoke. The handle leak went away.
Doron.
I actually see the same problem occuring as JYelton. I have the same call from within a thread to update the UI.
As soon as the line someControl.Invoke(new DelegateUIUpdate(UIUpdate)); is called, the handle increases by one. There is certainly a leak of some kind on the invoke, but I have no idea what is causing it. This has been verified on several systems.
Aync call with explicit handle finalize. Exapmle:
public static class ActionExtensions
{
private static readonly ILog log = LogManager.GetLogger(typeof(ActionExtensions));
/// <summary>
/// Async exec action.
/// </summary>
/// <param name="action">Action.</param>
public static void AsyncInvokeHandlers(
this Action action)
{
if (action == null)
{
return;
}
foreach (Action handler in action.GetInvocationList())
{
// Initiate the asychronous call. Include an AsyncCallback
// delegate representing the callback method, and the data
// needed to call EndInvoke.
handler.BeginInvoke(
ar =>
{
try
{
// Retrieve the delegate.
var handlerToFinalize = (Action)ar.AsyncState;
// Call EndInvoke to free resources.
handlerToFinalize.EndInvoke(ar);
var handle = ar.AsyncWaitHandle;
if (handle.SafeWaitHandle != null && !handle.SafeWaitHandle.IsInvalid && !handle.SafeWaitHandle.IsClosed)
{
((IDisposable)handle).Dispose();
}
}
catch (Exception exception)
{
log.Error("Async Action exec error.", exception);
}
},
handler);
}
}
}
See http://msdn.microsoft.com/en-us/library/system.iasyncresult.asyncwaithandle.aspx note:
When you use the BeginInvoke method of a delegate to call a method asynchronously and obtain a wait handle from the resulting IAsyncResult, we recommend that you close the wait handle as soon as you are finished using it, by calling the WaitHandle.Close method. If you simply release all references to the wait handle, system resources are freed when garbage collection reclaims the wait handle, but garbage collection works more efficiently when disposable objects are explicitly closed or disposed. For more information, see the AsyncResult.AsyncWaitHandle property.
Here's an extension method which functions similarly to the normal Invoke call, but will clean up the handle after:
namespace ExtensionMethods
{
public static class ExtensionMethods
{
public static void InvokeAndClose(this Control self, MethodInvoker func)
{
IAsyncResult result = self.BeginInvoke(func);
self.EndInvoke(result);
result.AsyncWaitHandle.Close();
}
}
}
You can then call it very similarly to a normal invoke:
myForm.InvokeAndClose((MethodInvoker)delegate
{
someControl.Text = "New Value";
});
It will block and wait for the delegate to execute, then close the handle before returning.
This is the standard pattern for using Invoke to marshall updates to the UI thread.
Are you sure your problem is not being caused by other code in your application that is not included in your question?
I don't think it is related. Perhaps just waiting for the garbage collector to dispose the newly allocated object(s) inside Invoke().

How to run a function for each element in a list on a different thread sequentially and update the (passive) view after each function has run?

I have a WinForm «Passive View» and a «Controller» where the controller is running a long running function for each element in a list.
I want the following:
The functions shall run sequentially
The view mustn't freeze while looping the list and running the functions
After each function has run, the view shall be updated with the result of the run
The (single-threaded) code looks like this as of now:
View.DateSpan.Workdays.ForEach(
d => {
var processRunInfo = _processRunner.Run( configFile, d );
UdateViewFrom( processRunInfo );
} );
The code above "works" but causes the view to freeze since it uses the very same thread, and it updates the view batch-wise.
Workdays is an IEnumerable<DateTime>, and ForEach does what ForEach of List<T> does but is an extension method from MoreLINQ.
_processRunner.Run runs an external command line application with the arguments supplied.
Running the foreach loop in a separate thread with a callback to the Invoke of your control (form) would be my solution.
The link below contains a decent example.
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
You should make long-running calculation in the separate thread (not the main GUI thread), so that main thread that have message loop can be free.
Than, inside of for-each loop, you should marshal UpdateViewForm method to the GUI thread using Control.Invoke method. You can choose to wrap methods in PassiveView, like this:
public void DoSomething() {
if (this.InvokeRequired) {
this.Invoke(DoSomethingDelegate);
...
}
}
or just, instead of standard method invocation, use something like this:
myFormControl1.Invoke(myFormControl1.myDelegate);
+1 to Nenad and Bastiaan for pointing me in the Control.Invoke direction.
In order to fully reap the benefits of the «passive view» pattern, I don't want any knowledge of the Control type of WinForms in the «supervising controller» (that type should only be known by the implementer of the view interface, i.e. the one derived from Form).
Here's how I solved the issue satisfactory:
The controller creates a new Thread instance with the ForEach loop a an argument, and then starts the created instance.
Before:
View.DateSpan.Workdays.ForEach(d =>
{
// do stuff...
} );
After:
new Thread( () => View.DateSpan.Workdays.ForEach( d =>
{
// do stuff...
} ) ).Start();
The view's widget update methods use a helper method that checks if the request comes from another thread, and if so uses Invoke. See the code below.
Before:
public string Status
{
set { _statusLabel.Text = value ); }
}
After:
public string Status
{
set { ExecuteOnUIThread( _statusLabel, () => _statusLabel.Text = value ); }
}
The helper method:
private static void ExecuteOnUIThread( Control control, Action action )
{
if ( control.InvokeRequired )
{
control.Invoke( action );
}
else
{
action();
}
}
The production WinForm view works like a charm, and with the addition of a while loop that spins the thread while the background thread does its work in my BDD stories, so do they with my old view «test spy».
Another option would be to take advantage of PLINQ - Parallel Linq
http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
And you could do something like
View.DateSpan.Workdays.AsParallel().ForEach(
d => {
var processRunInfo = _processRunner.Run( configFile, d );
UdateViewFrom( processRunInfo );
} );
You would still most likely have to handle the return update in a callback event.

Categories

Resources