I am using the C wrapper of UIAutomation to listen for events.
Specifically, I'm looking for a focus event. When that focus event happens, I'm simply logging to the console, and unbinding the event.
Problem is - the program seems to stall/"die" on the automation.RemoveAllEventHandlers() call. The line below that never gets executed (doesn't print to console, breakpoint doesn't get hit.)
My guess is this is a threading issue - automationis created on a thread, but the event gets called on a different thread, and a big issue ensues. Is this the problem? If so/if not - what is and how do I fix it?
Below is the code:
public class FocusListener
{
private readonly CUIAutomation _automation;
public FocusListener()
{
_automation = new CUIAutomation();
_automation.AddFocusChangedEventHandler(null, new FocusChangeHandler(this));
Console.WriteLine("Added a focus event!");
}
public void On_WindowClicked()
{
Console.WriteLine("Window clicked!");
_automation.RemoveAllEventHandlers(); // program seems to die right here..
Console.WriteLine("Focus event removed"); // this line never gets executed..
}
}
public class FocusChangeHandler : IUIAutomationFocusChangedEventHandler
{
private readonly FocusListener _listener;
public FocusChangeHandler(FocusListener listener)
{
_listener = listener;
}
public void HandleFocusChangedEvent(IUIAutomationElement sender)
{
if (sender.CurrentControlType == UIA_ControlTypeIds.UIA_WindowControlTypeId)
{
_listener.On_WindowClicked();
}
}
}
According to: https://msdn.microsoft.com/en-us/library/windows/desktop/ee671692%28v=vs.85%29.aspx
It is safe to make UI Automation calls in a UI Automation event handler, >because the event handler is always called on a non-UI thread. However, when >subscribing to events that may originate from your client application UI, you >must make the call to IUIAutomation::AddAutomationEventHandler, or a related >method, on a non-UI thread (which should also be an MTA thread). Remove event >handlers on the same thread.
Related
Is it true that event in Unity's Monobehavior is single threaded? When I trigger an event, if one of the listener raises an exception, the catch block will be executed. I assume once class A fires an event, the thread will go over each subscriber. When each subscriber finishes, does class A continue in the same thread?
public class EventExample : MonoBehaviour
{
public delegate void ExampleEventHandler();
public static event ExampleEventHandler OneDayPassed;
public void Start NextTurn()
{
try {
if (OneDayPassed != null)
{
OneDayPassed();
}
}
catch(Exception e)
{
// will catch error here
}
}
}
public class EntityWatcher : MonoBehaviour
{
void Start()
{
EventExample.OneDayPassed += this.PrepareNextDay;
}
public void PrepareNextDay()
{
int test = int.parse("error");
}
}
Monobehavior is mostly single Threaded but some few callback functions are not. Most of the Unity API callback functions will be made on the main Thread.
These are the fnctions that will not be called on the main Thread which means that you can't call/use the Unity API inside these functions:
Application.RegisterLogCallbackThreaded
Application.logMessageReceivedThreaded event
OnAudioFilterRead Monobehavior callback function.
As for your own custom event like:
public delegate void ExampleEventHandler();
public static event ExampleEventHandler OneDayPassed;
The event is called on the Thread you invoked it from. If you call it from the main/MonoBehaviour thread, the callback will happen on the main thread. If you create a new Thread and call it from there or use any of the 3 functions listed above then expect it to be called on another Thread other than the main Thread.
If you need to use Unity's API from another Thread other than the main Thread then see this post.
Unity's event API is single-threaded. And also, is not designed to support multi-threading (not thread-safe).
Of course, you can explicitly delegate some work with multi-threading if you want, but don't try to call the Unity API with these.
You can have some more information here : https://answers.unity.com/questions/180243/threading-in-unity.html
If you need to rely on some execution order, you can refer to the manual page here
I have a class with EventHandler bindings at the constructor, that will be instantiated thousand times within application lifecycle. The question is: Will this approach leads to memory/thread leaks?
I did this way (code below), because I need to be notified every time SomeMethod() runs, whatever instance run it. Foo class (the publisher) will be short-lived, however the handlers will live until the application closes.
I ask this because, when working with Windows Forms, each form can hold several event handlers/delegates and everything is fine because all those delegates are inside the form and will be disposed when the form closes. But how about static event handlers/delegates, that could be even on separate projects?
Will I need to write a destructor to detach those event handlers?
Should I go with Weak Event Pattern?
Restriction: I must do this with .NET 3.5. I know I could do this with TPL, setting a "Fire and Forget" Task.
Thank you in advance.
Code:
public class Foo
{
public event EventHandler SomeEvent;
public Foo()
{
SomeEvent += FooHandlers.Foo_SomeEvent1;
SomeEvent += FooHandlers.Foo_SomeEvent2;
}
public void RaiseEvents(EventHandler evt, EventArgs args)
{
var eventObj = evt;
var listeners = eventObj.GetInvocationList();
foreach (var listener in listeners)
{
var method = (EventHandler)listener;
ThreadPool.QueueUserWorkItem(callBack => method(this, args));
// Handlers will do a lot of things, so I don't want
// them blocking the Main thread
}
}
public void SomeMethod()
{
// do something here
RaiseEvents(SomeEvent, new EventArgs());
}
}
public static class FooHandlers
{
public static void Foo_SomeEvent1(object sender, EventArgs e)
{
//do something here
}
public static void Foo_SomeEvent2(object sender, EventArgs e)
{
//do something different here
}
}
Since your handlers are static methods the delegate you're adding to the event doesn't have an object instance, so there is no object instance being kept alive for the duration of the object with the event.
And even if you did use an object instance to attach the handler, it wouldn't be a problem, because the object with the event is short lived. The only time there is a problem is when the object with the event is long lived, and the object that has a handler to itself assigned is short lived, and consumes a lot of resources to keep alive.
I've been writing an API that facilitates communication with a serial port. I'm doing some refactoring and general cleanup and was wondering if there's a way to avoid the following issue.
The main class in the API has the capability to constantly read from the port and raise an event containing a value when the read bytes match a particular regex. The process of reading and parsing occurs on another thread. The event contains the value as an argument (string) and because it's being raised from another thread, a client attempting to directly assign the value to, say, the Text property of a control causes a cross-thread exception unless the handler has the proper Invoke code.
I understand why this happens, and when I put the proper invocation code in my test client's event handler, all is well; my question is whether or not there's anything I can do in the API code itself such that clients don't have to worry about it.
Essentially, I'd like to turn this:
void PortAdapter_ValueChanged(Command command, string value)
{
if (this.InvokeRequired)
{
Invoke(new MethodInvoker(() =>
{
receivedTextBox.Text = value;
}));
}
else
{
receivedTextBox.Text = value;
}
}
into simply this:
void PortAdapter_ValueChanged(Command command, string value)
{
receivedTextBox.Text = value;
}
Well there is a common pattern for that used many places in .Net framework itself. For example BackgroundWorker uses this model.
For that you'll take a SynchronizationContext as a parameter for your API, in this case I assume it is PortAdapter.
When raising an event, you raise the event in given SynchronizationContext using SynchronizationContext.Post or SynchronizationContext.Send. Former is asynchronous and latter is synchronous.
So, when client code creating a instance of your PortAdapter, it passes WindowsFormsSynchronizationContext instance as parameter. Which means that PortAdapter will raise the event in given synchronization context and that also means that you don't need a InvokeRequired or Invoke calls.
public class PortAdapter
{
public event EventHandler SomethingHappened;
private readonly SynchronizationContext context;
public PortAdapter(SynchronizationContext context)
{
this.context = context ?? new SynchronizationContext();//If no context use thread pool
}
private void DoSomethingInteresting()
{
//Do something
EventHandler handler = SomethingHappened;
if (handler != null)
{
//Raise the event in client's context so that client doesn't needs Invoke
context.Post(x => handler(this, EventArgs.Empty), null);
}
}
}
Client code:
PortAdapter adpater = new PortAdapter(SynchronizationContext.Current);
...
It is very important to create instance of PortAdapter in UI thread, otherwise SynchronizationContext.Current will be null and hence events will be still raised in ThreadPool thread.
More about SynchronizationContext here.
TBH, the approach with checking for InvokeRequired is fine and flexible.
But if you like, you can have all events in your application UI-safe. For this either all classes have to have invocation control registered
public class SomeClassWithEvent
{
private static Control _invoke = null;
public static void SetInvoke(Control control)
{
_invoke = control;
}
public event Action SomeEvent;
public OnSomeEvent()
{
// this event will be invoked in UI thread
if (_invoke != null && _invoke.IsHandleCreated && SomeEvent != null)
_invoke.BeginInvoke(SomeEvent);
}
}
// somewhere you have to register
SomeClassWithEvent.SetInvoke(mainWindow);
// and mayhaps unregister
SomeClassWithEvent.SetInvoke(null);
or have that invocation control exposed, to example:
// application class
public static class App
{
// will be set by main window and will be used even risers to invoke event
public static MainWindow {get; set;}
}
You will have difficulties if event occur when no handle is created or control registered.
You can trigger the event in the UI Thread, this way the event handler (if any) will already be in the UI thread.
public class PortAdapter
{
public event EventHandler<string> ValueChanged;
protected virtual void OnValueChanged(string e)
{
var handler = ValueChanged;
if (handler != null)
{
RunInUiThread(() => handler(this, e));
}
}
private void RunInUiThread(Action action)
{
if (InvokeRequired)
{
Invoke(action);
}
else
{
action.Invoke();
}
}
}
However this is not good design because you don't know if an handler will perform UI interaction.
I have an event handler in a class which doesnt seem to trigger. I wonder if anyone had any ideas on why this may be happening (or not happening as is the case).
The class inherits from another class and basically listens for messages from a message queue. When a message hits the queue the method onMessage() is called.
From my (winforms, c#, .net 3.5) UI form, I'm trying to get the received message(s) back to the UI.
If I call the method onMessage() manually from the instance on my form, the eventhandler does trigger correctly and passMessage is executed on my UI form.
But when I receive a message thats come automated from the queue I'm listening on, the event handler is not triggered. I dont ever call the onMessage() method, that happens automatically.
Does anyone have any ideas why the event handler is not triggering when onMessage() is called everytime I receive a message?
Thanks
UI:
private void btnConnect(object sender, EventArgs e)
{
MessageQueue myMQ = new MessageQueue();
myMQ.Connect(...);
//Register handler
myMQ.MsgTrigger += new EventHandler(passMessage);
}
public void passMessage(object s, EventArgs e)
{
Console.WriteLine(s.ToString()); //Not sure if this is a good way to pass back a value
}
Class:
namespace MQListener
{
class MessageQueue : MQ.MessageListener
{
public event EventHandler MsgTrigger;
public virtual void onMessage(MQ.Message Message)
{
MQ.TextMessage txtMessage = (MQ.TextMessage)Message;
String MsgBody = txtMessage.getMessage();
Console.WriteLine(MsgBody);
object objMsg = (object)MsgBody;
var _Trigger = MsgTrigger;
if(_Trigger != null)
_Trigger(objMsg, null);
}
}
}
Your event subscription should happen before you connect:
private void btnConnect(object sender, EventArgs e)
{
MessageQueue myMQ = new MessageQueue();
//Register handler
myMQ.MsgTrigger += new EventHandler(passMessage);
myMQ.Connect(...);
}
You can only update controls from the UI thread, so to prevent the error "'txtMessage' accessed from a thread other than the thread it was created on.", you need to check the control's InvokeRequired property. If true, you need to call the Invoke() method. See this SO question: Automating the InvokeRequired code pattern
I have a C# 2.0 application with a form that uses a class that contains a thread.
In the thread function, rather than call the event handler directly, it is invoked. The effect is that the owning form does not need to call InvokeRequired/BeginInvoke to update its controls.
public class Foo
{
private Control owner_;
Thread thread_;
public event EventHandler<EventArgs> FooEvent;
public Foo(Control owner)
{
owner_ = owner;
thread_ = new Thread(FooThread);
thread_.Start();
}
private void FooThread()
{
Thread.Sleep(1000);
for (;;)
{
// Invoke performed in the thread
owner_.Invoke((EventHandler<EventArgs>)InternalFooEvent,
new object[] { this, new EventArgs() });
Thread.Sleep(10);
}
}
private void InternalFooEvent(object sender, EventArgs e)
{
EventHandler<EventArgs> evt = FooEvent;
if (evt != null)
evt(sender, e);
}
}
public partial class Form1 : Form
{
private Foo foo_;
public Form1()
{
InitializeComponent();
foo_ = new Foo(this);
foo_.FooEvent += OnFooEvent;
}
private void OnFooEvent(object sender, EventArgs e)
{
// does not need to call InvokeRequired/BeginInvoke()
label_.Text = "hello";
}
}
This is obviously contrary to the method used by Microsoft APIs that use background threads like System.Timers.Timer and System.Io.Ports.SerialPort. Is there anything inherently wrong with this method? Is it dangerous in some way?
Thanks,
PaulH
Edit: also, what if the form did not subscribe to the event right away? Would it clog the Form's message queue with events the form wasn't interested in?
This is a threadsafe call, the method will be processed in the thread of the form.
Nothing wrong with it when looking at it from a conceptual perspective.
Timers are more elegant for such tasks, though. However, it could be that a timer with an interval of 10ms slows down the GUI, that's probably why Invoke was used.
You do not need a call to InvokeRequired, since it is clear that the Control is in an other thread. Also, BeginInvoke only needs to be called when you want to call a method asynchronously, which obviously isn't the case here.
Regarding your edit:
No, the message queue will not be clogged. No event will be fired if no handler has been registered. Take another look at your code ;)