Invoking method on thread which created object - c#

Let's say I created an object O on the thread T. How can I get, from inside object O the thread T and invoke a method on that thread?. This way, it won't be necessary for the form that created the object to to this:
private void ChangeProgress(int value)
{
progressBar1.Value = value;
}
void FD_ProgressChanged(object sender, DownloadEventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<int>(ChangeProgress), new object[] { e.PercentDone });
}
else ChangeProgress(e.PercentDone);
}
which is just ugly and requires whoever uses the object to either figure out which events are raised on the same thread that created the object and which are not and add the if(InvokeRequired)...else code on the ones that are not, or just add the code on every single event handler. I think it would be more elegant if the object itself takes care of invoking the event on the right thread. Is this possible?

Use the BackgroundWorker class. It takes care of all this. Note the ReportProgress event.

You are going to have to track it yourself like
class Foo {
private readonly Thread creatingThread;
public Foo() {
this.creatingThread = Thread.CurrentThread;
}
}
If you don't do that, there is no way to know. But the fact that you are doing this is a smell. Consider using a BackgroundWorker.

There are a few thing you need to consider:
You will need to keep a reference in Object O of a thread that it was created in. Probably in a constructor using Thread.Current static property.
That thread will need to have a SynchronizationContext associated with it. (Generally, UI threads have it. And its not easy to create one for a custom thread you created.)
To invoke a method on that thread, you will need to use Send() or Post() methods on that thread's SynchronizationContext.

Found a nice solution at http://www.codeproject.com/KB/threads/invoke_other_way.aspx
And here's is my generic version:
private void RaiseEventAsync(Delegate handler, object e)
{
if (null != handler)
{
List<Delegate> invocationList = handler.GetInvocationList().ToList();
foreach (Delegate singleCast in invocationList)
{
System.ComponentModel.ISynchronizeInvoke syncInvoke =
singleCast.Target as System.ComponentModel.ISynchronizeInvoke;
try
{
if ((null != syncInvoke) && (syncInvoke.InvokeRequired))
syncInvoke.Invoke(singleCast,
new object[] { this, e });
else
singleCast.Method.Invoke(singleCast.Target, new object[] { this, e });
}
catch
{ }
}
}
}
And this is how you would use it:
protected void OnProgressChanged(DownloadEventArgs e)
{
RaiseEventAsync(ProgressChanged, e);
}
This takes care of my problem without needing to use a BackgroundWorker that is not always wanted (like on my case, where I'm subclassing a class that already uses a different threading object).

Related

C# Call a showdialog inside backgroundworker from a Class library [duplicate]

I am working on a VS project/solution that is used by different applications. My job is to refactor the project and change it from using xxxAsync method to using BeginInvoke.
I came up to something similar to the following code:
public class AsyncTestModel {
private delegate string DoTaskDelegate();
public static EventHandler<TaskCompletedEventArgs> OnTaskCompleted;
public static void InvokeTask() {
DoTaskDelegate taskDelegate = Task;
taskDelegate.BeginInvoke(new AsyncCallback(TaskCallback), null);
}
private static string Task() {
Thread.Sleep(5000);
return "Thread Task successfully completed.";
}
private static void TaskCallback(IAsyncResult ar) {
string result = ((DoTaskDelegate)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
if (OnTaskCompleted != null) {
OnTaskCompleted(null, new TaskCompletedEventArgs(result));
}
}
}
public class TaskCompletedEventArgs : EventArgs {
private string _message;
public TaskCompletedEventArgs(string message) : base() {
_message = message;
}
public string Message {
get {
return _message;
}
}
}
I've tested this on a new UI project I've created. The UI project contains a button and a label controls. The UI has the following code:
private void button1_Click(object sender, EventArgs e) {
AsyncTestModel.OnTaskCompleted += OnTaskCompleted;
AsyncTestModel.InvokeTask();
}
private void OnTaskCompleted(object sender, TaskCompletedEventArgs e) {
UpdateLabel(e.Message);
}
private void UpdateLabel(string message) {
this.label1.Text = message;
}
After running this, I've encountered the cross-thread exception saying the the control 'label1' is being accessed from other thread aside the thread that it was created.
Is there a way for me to invoke the OnTaskCompleted event handler on the same thread that calls the BeginInvoke method? I know I could just use the form's InvokeRequired and call the form's BeginInvoke like the following:
private delegate void DoUpdateLabelDelegate(string message);
private void UpdateLabel(string message) {
if (this.InvokeRequired) {
IAsyncResult ar = this.BeginInvoke(new DoUpdateLabelDelegate(UpdateLabel), message);
this.EndInvoke(ar);
return;
}
this.label1.Text = message;
}
But the solution above will require me to ask and apply that solution to the other development team handling applications that uses my project/solution. Those other developers shouldn't be required to know that the methods hooked to the event handler are running from different thread.
Thanks, in advance.
As designed, no, you have absolutely no idea which thread is the one on which the client's UI runs.
You can arbitrarily demand that your InvokeTask() is to be called from that UI thread. Now you know, you can copy SynchronizationContext.Current in the InvokeTask() method and, later, call its Post() or Send() method to call a method that fires the event. This is the pattern used by, for example, BackgroundWorker and async/await. Do note that copying the Current property is required to make this work, don't skip it.
That of course still won't work when your InvokeTask() method is not called from the UI thread, you'll see that Synchronization.Current is null and have no hope to marshal the call. If that's a concern then you could expose a property of type ISynchronizeInvoke, call it SynchronizingObject. Now it is up to the client code to make the call, they'll have no trouble setting the property, they'll simply assign this in their form class constructor. And you use the property's Post or Send method to call the method that raises the event. This is the pattern used by for example the Process and FileSystemWatcher classes. Don't use it if you expect your library to be used by non-Winforms client apps, unfortunately later GUI libraries like WPF and Silverlight don't implement the interface. Otherwise the exact same problem with approaches like calling Control.Begin/Invoke() yourself.
try to use this, maybe it can help you.
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//Do something...
});

Creating a thread to handle events for a particular class

I have a WPF application and I need to listen to, and handle events for the lifetime of the application for a certain class.
Is it bad practice to create a wrapper class, create a static instance of it and call "StartListening()"? What if an unhanded exception happens on this static instance? Will it tear down the entire application as it would in an ASP.NET application?
Should I QueueUserWorkItem, create the class, attach events, and then put some kind of while(true){} statement to keep the thread alive?
What is the best practice?
To me this seems like a classic publisher/listener problem.
I would create an interface: IMyClassNameEventListener and make MyClass take an instance of it as a constructor parameter. Then in the constructor I would call the Attach(MyClass obj) method on the interface instance. Of course, the listener would have a singleton lifecycle, it doesn't need to be static.
A slightly better approach would be to use a factory to create instances of MyClass which would then do the attaching, so the Attach call and the dependency are out of the constructor.
Wether the app would fail would be dependent on how you start the listener. You can look into the TaskFactory class, it provides options to handle exception propagation. How would you want the app to behave if the listener fails?
Of course in the listener object itself, you only need to have code run when there is something to handle. So, when you receive an event, you startup a thread. You can use a queue of actions if you'd want to have only one thread running.
Inside the listener class, you might want to have something like the following:
private Queue<Action> ActionQueue = new Queue<Action>();
private object LockObj = new Object();
private volatile bool IsRunning;
public void Attach(Class1 obj)
{
obj.SomeEvent += this.HandleEvent;
}
private void HandleEvent(object sender, EventArgs e)
{
lock(this.LockObj)
{
this.ActionQueue.Enque(() => this.Handle(sender, e));
if (!this.IsRunning)
{
Task.Factory.StartNew(() => this.Loop() );
}
}
}
private void Loop()
{
this.IsRunning = true;
while ((Action action = this.DequeueAction()) != null)
action();
this.IsRunning = false;
}
private Action DequeueAction()
{
lock (this.LockObj)
{
return this.ActionQueue.Count > 0 ? this.ActionQueue.Dequeue() : null;
}
}
private void Handle(object sender, EventArgs e)
{
//handling code
}

Creating a class with thread safe functions using InvokeRequired property and Invoke method

I have a class that I created and in the class I do some multi-threading. Usually to do my multi-threading on a form I would use the following method...
//Thread Safe Functions
delegate void Thread_Safe_SendMessage_Progress_Callback(string sProgress);
private void Thread_Safe_SendMessage_Progress(string sProgress)
{
if (this.InvokeRequired)
{
Thread_Safe_SendMessage_Progress_Callback d =
new Thread_Safe_SendMessage_Progress_Callback(Thread_Safe_SendMessage_Progress);
try
{
this.Invoke(d, new object[] { sProgress });
}
catch
{
//ObjectDisposedException
}
}
else
{
//Fire up the thread event
SendMessageThread_Progress(sProgress);
}
}
Now that works perfect! At this point I try to bring the multi-threading into a class i made. When I do that everything seems to be great with the exception of the InvokeRequired property and the Invoke method do not exist within my class. So using this.InvokeRequired throws an error... To give my class that property I do this... (Note that m_iThreadID is set in the constructor and when the thread is created to start with)
private bool InvokeRequired
{
get
{
//Get the current thread id
int iThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
//Compare and return results
return (iThreadID != m_iThreadID);
}
}
Now the only thing left is the Invoke method... How do I get that to work?
Invoke method isn't so "easy" to replicate (side question: why don't you use BeginInvoke? I guess you may don't need to raise the event synchronously). You can get the first form in Application.OpenForms (copy before use!) and inspect that to check for InvokeRequired and BeginInvoke/Invoke.

Detecting whether on UI thread in WPF and Winforms

I've written an assertion method Ensure.CurrentlyOnUiThread(), below, that checks that the current thread is a UI thread.
Is this going to be reliable in detecting the Winforms UI thread?
Our app is mixed WPF and Winforms, how best to detect a valid WPF UI thread?
Is there a better way to do this? Perhaps code contracts?
Ensure.cs
using System.Diagnostics;
using System.Windows.Forms;
public static class Ensure
{
[Conditional("DEBUG")]
public static void CurrentlyOnUiThread()
{
if (!Application.MessageLoop)
{
throw new ThreadStateException("Assertion failed: not on the UI thread");
}
}
}
Don't use
if(Dispatcher.CurrentDispatcher.Thread == Thread.CurrentThread)
{
// Do something
}
Dispatcher.CurrentDispatcher will, if the current thread do not have a dispatcher, create and return a new Dispatcher associated with the current thread.
Instead do like this
Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
if (dispatcher != null)
{
// We know the thread have a dispatcher that we can use.
}
To be sure you have the correct dispatcher or are on the correct thread you have the following options
Dispatcher _myDispatcher;
public void UnknownThreadCalling()
{
if (_myDispatcher.CheckAccess())
{
// Calling thread is associated with the Dispatcher
}
try
{
_myDispatcher.VerifyAccess();
// Calling thread is associated with the Dispatcher
}
catch (InvalidOperationException)
{
// Thread can't use dispatcher
}
}
CheckAccess() and VerifyAccess() do not show up in intellisense.
Also, if you have to resort to these kinds of things its likely due to bad design. You should know which threads run what code in your program.
For WPF, I use the following:
public static void InvokeIfNecessary (Action action)
{
if (Thread.CurrentThread == Application.Current.Dispatcher.Thread)
action ();
else {
Application.Current.Dispatcher.Invoke(action);
}
}
The key is instead of checking Dispatcher.CurrentDispatcher (which will give you the dispatcher for the current thread), you need to check if the current thread matches the dispatcher of the application or another control.
Within WinForms you would normally use
if(control.InvokeRequired)
{
// Do non UI thread stuff
}
for WPF
if (!control.Dispatcher.CheckAccess())
{
// Do non UI Thread stuff
}
I would probably write a little method that uses a Generic constraint to determine which of these you should be calling. e.g.
public static bool CurrentlyOnUiThread<T>(T control)
{
if(T is System.Windows.Forms.Control)
{
System.Windows.Forms.Control c = control as System.Windows.Forms.Control;
return !c.InvokeRequired;
}
else if(T is System.Windows.Controls.Control)
{
System.Windows.Controls.Control c = control as System.Windows.Control.Control;
return c.Dispatcher.CheckAccess()
}
}
For WPF:
// You are on WPF UI thread!
if (Thread.CurrentThread == System.Windows.Threading.Dispatcher.CurrentDispatcher.Thread)
For WinForms:
// You are NOT on WinForms UI thread for this control!
if (someControlOrWindow.InvokeRequired)
Maybe Control.InvokeRequired (WinForms) and Dispatcher.CheckAccess (WPF) are OK for you?
You're pushing knowledge of your UI down into your logic. This is not a good design.
Your UI layer should be handling threading, as ensuring the UI thread isn't abused is within the purview of the UI.
This also allows you to use IsInvokeRequired in winforms and Dispatcher.Invoke in WPF... and allows you to use your code within synchronous and asynchronous asp.net requests as well...
I've found in practice that trying to handle threading at a lower level within your application logic often adds lots of unneeded complexity. In fact, practically the entire framework is written with this point conceded--almost nothing in the framework is thread safe. Its up to callers (at a higher level) to ensure thread safety.
Here is a snippet of code I use in WPF to catch attempts to modify UI Properties (that implement INotifyPropertyChanged) from a non-UI thread:
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
// Uncomment this to catch attempts to modify UI properties from a non-UI thread
//bool oopsie = false;
//if (Thread.CurrentThread != Application.Current.Dispatcher.Thread)
//{
// oopsie = true; // place to set a breakpt
//}
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
For WPF:
I've needed to know is Dispatcher on my thread is actually started, or not. Because if you create any WPF class on the thread, the accepted answer will state that the dispatcher is there, even if you never do the Dispatcher.Run(). I've ended up with some reflection:
public static class WpfDispatcherUtils
{
private static readonly Type dispatcherType = typeof(Dispatcher);
private static readonly FieldInfo frameDepthField = dispatcherType.GetField("_frameDepth", BindingFlags.Instance | BindingFlags.NonPublic);
public static bool IsInsideDispatcher()
{
// get dispatcher for current thread
Dispatcher currentThreadDispatcher = Dispatcher.FromThread(Thread.CurrentThread);
if (currentThreadDispatcher == null)
{
// no dispatcher for current thread, we're definitely outside
return false;
}
// get current dispatcher frame depth
int currentFrameDepth = (int) frameDepthField.GetValue(currentThreadDispatcher);
return currentFrameDepth != 0;
}
}
You can compare thread ids like this :
var managedThreadId = System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread)?.Thread.ManagedThreadId;
var dispatcherManagedThreadId = System.Windows.Application.Current.Dispatcher.Thread.ManagedThreadId;
if (managedThreadId == dispatcherManagedThreadId)
{
//works in ui dispatcher thread
}
Using MVVM it is actually fairly easy. What I do is put something like the following in, say, ViewModelBase...
protected readonly SynchronizationContext SyncContext = SynchronizationContext.Current;
or...
protected readonly TaskScheduler Scheduler = TaskScheduler.Current;
Then when a particular ViewModel needs to touch anything "observable", you can check the context and react accordingly...
public void RefreshData(object state = null /* for direct calls */)
{
if (SyncContext != SynchronizationContext.Current)
{
SyncContext.Post(RefreshData, null); // SendOrPostCallback
return;
}
// ...
}
or do something else in the background before returning to context ...
public void RefreshData()
{
Task<MyData>.Factory.StartNew(() => GetData())
.ContinueWith(t => {/* Do something with t.Result */}, Scheduler);
}
Normally, if you follow MVVM (or any other architecture) in an orderly fashion, it is easy to tell where the responsibility for UI synchronization will be situated. But you can basically do this anywhere to return to the context where your objects are created. I'm sure it would be easy to create a "Guard" to handle this cleanly and consistently in a large and complex system.
I think it makes sense to say that your only responsibility is to get back to your own original context. It is a client's responsibility to do the same.
FOR WPF:
Here's a snippet based on the top answer, using a delegate meaning it is very generic.
/// <summary>
/// Invokes the Delegate directly on the main UI thread, based on the calling threads' <see cref="Dispatcher"/>.
/// NOTE this is a blocking call.
/// </summary>
/// <param name="method">Method to invoke on the Main ui thread</param>
/// <param name="args">Argumens to pass to the method</param>
/// <returns>The return object of the called object, which can be null.</returns>
private object InvokeForUiIfNeeded(Delegate method, params object[] args)
{
if (method == null) throw new ArgumentNullException(nameof(method));
var dispatcher = Application.Current.Dispatcher;
if (dispatcher.Thread != Thread.CurrentThread)
{
// We're on some other thread, Invoke it directly on the main ui thread.
return dispatcher.Invoke(method, args);
}
else
{
// We're on the dispatchers' thread, which (in wpf) is the main UI thread.
// We can safely update ui here, and not going through the dispatcher which safes some (minor) overhead.
return method.DynamicInvoke(args);
}
}
/// <inheritdoc cref="InvokeForUiIfNeeded(Delegate, object[])"/>
public TReturn InvokeForUiIfNeeded<TReturn>(Delegate method, params object[] args)
=> (TReturn) InvokeForUiIfNeeded(method, args);
The second method allows for a more type safe return type.
I've also added some overloads that automatically take the Func and Action parameters in my code, e.g:
/// <inheritdoc cref="InvokeForUiIfNeeded(System.Delegate, object[])"/>
private void InvokeForUiIfNeeded(Action action)
=> InvokeForUiIfNeeded((Delegate) action);
Note; the Func and Action inherit from Delegate so we can just cast it.
You could also add your own generic overloads that take actions, i did not bother creating a bunch of overloads but you definitely could e.g;
/// <inheritdoc cref="InvokeForUiIfNeeded(System.Delegate, object[])"/>
private void InvokeForUiIfNeeded<T1>(Action<T1> action, T1 p1)
=> InvokeForUiIfNeeded((Delegate)action, p1);
/// <inheritdoc cref="InvokeForUiIfNeeded(System.Delegate, object[])"/>
private TReturn InvokeForUiIfNeeded<T1, TReturn>(Func<T1, TReturn> action, T1 p1)
=> (TReturn)InvokeForUiIfNeeded((Delegate)action, p1);
Thread.CurrentThread.ManagedThreadId == Dispatcher.Thread.ManagedThreadId
Is a better way to check this

Calling Invoke/BeginInvoke from a thread

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 ;)

Categories