System.Timers.Timer need to get back to 'Main' thread - c#

I have a Class(call it 'Foo') that has a System.Timers.Timer(call it 'myTimer').
Foo wraps unmanaged non thread-safe code.
On myTimer.Elapsed I need to use Methods in Foo.
Right now myTimer is trying use Foo's Methods on worker threads and this isn't working.
I need to get back to the thread that contains Foo' Methods.
How do I accomplish this?
FYI, Foo's Methods are in a non-UI thread.

If Foo is not a UI thread and you need to invoke code to execute on it from a different thread you will need to capture the synchronization context which executes Foo and then invoke your code from the timer on it.
Take a look at the SynchronizationContext class. You can either Post (asynchronously) or Send a delegate to be executed on a specific, previously captured, synchronization context.
You may also want/need to look into the ExecutionContext class. In particular: ExecutionContext.Capture and ExecutionContext.Run

Related

Is it possible to control the SynchronizationContext used by a .NET Progress<T> object?

From the Progress<T> Class reference page:
Any handler provided to the constructor or event handlers registered with the ProgressChanged event are invoked through a SynchronizationContext instance captured when the instance is constructed. If there is no current SynchronizationContext at the time of construction, the callbacks will be invoked on the ThreadPool.
I'm creating a Progress<int> on a background thread. I want the callbacks, and any associated cancellations (throwing an OperationCancelledException), to occur on the same thread.
At the time of constructing the Progress<int> object, SynchronizationContext.Current is null.
And so, as the above documentation tells me, the callbacks are being executed on the Thread Pool...
Questions
Is it possible to do anything about the fact that the current SynchronizationContext is null? For example, create one for the current thread?
If that is possible, would the Progress<T> capture that SynchronizationContext?
If that is possible, would that reliably mean that the callbacks are executed on the same thread? As, I've read in other places, such as this SO answer, that:
...a SynchronizationContext does not necessarily represent a specific thread; it can also forward invocation of the delegates passed to it to any of several threads (e.g. to a ThreadPool worker thread)...
Solution/workaround
To make sure that callbacks are happening on the same thread, I'm using my own implementation of the IProgress<T> interface:
public class SynchronousProgress<T> : IProgress<T>
{
private readonly Action<T> action;
public SynchronousProgress(Action<T> action)
{
this.action = action;
}
public void Report(T value)
{
action(value);
}
}
It works. However, I'm still wondering if there is a way to achieve this with the .NET Progress<T> class?
Update: background information
The attempted usage of the Progress<T> class sits inside a custom, cancellable progress dialog, which encapsulates doing some work and reporting progress. In this case, the work (that can be cancelled) is occuring on the other side of a plugin boundary. It's desirable to use a .NET type (e.g. IProgress<T>) in the plugin interface for communicating progress, rather than a custom type (e.g. our own, (older) IProgress type).
The callback being given to the .NET IProgress<T> implementation, is simply an instruction to increment the progress of the custom IProgress implementation. Along the lines of:
public void Export(CulturedStreamWriter writer, IProgress progress) // that's a custom IProgress
{
progress.Steps = toExport.Count;
exporter.Export(toExport, writer, new SynchronousProgress<int>(progress.StepTo)); // increment the progress of the custom IProgress
}
Using the .NET Progress<T> in place of the SynchronousProgress<T> does not work, as cancellation exceptions are being thrown on a different thread to this code, which is where they need to be caught.
Seems as the custom implementation of the .NET IProgress<T> is working (SynchronousProgress<T>), perhaps it is in fact the most appropriate approach (given the surrounding code/constraints).
You can set SynchronizationContext.Current before constructing the instance to a value of your choice. Reset it afterwards (with a finally block to make sure you don't permanently mess up the thread).
This is a bit ugly. WebClient requires the same thing (unrelated to this question - just an example). I find it an API omission in Progress<T> that you can't provide the sync context. You could consider opening an issue on GitHub as a public service.
If you want to can just fork the source code of Progress<T> and add a constructor argument for the sync context. It's a small, self-contained class.
If that is possible, would that reliably mean that the callbacks are executed on the same thread?
They would run wherever that sync context chooses to run them. Depends on the context.
Your own implementation really just runs the callback right now which seems pointless. This IProgress implementation behaves just like an event that does not know anything about threads. It will not target any thread in particular. I doubt this is what you need although I can't be sure.

Is it possible to give callback for threads created using Thread class

Is it possible to give callback(announcing completion of activity) for threads created using Thread class. I have created the thread the following way but could not find a way to give the callback.
Thread thread = new Thread(StartPoll);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Not directly. But you can always do something like:
new Thread(() => { StartPoll(); Callback(); })
Setting the apartment state to STA is not enough, the second requirement is that you must pump a message loop. Application.Run() in either Winforms or WPF. It is actually the message loop that permits marshaling a call to a specific thread. Implemented by respectively Control.Begin/Invoke and Dispatcher.Begin/Invoke().
That's however more of a UI implementation detail. The generic solution is very similar to what the UI thread does, you use a thread-safe queue and a loop in the "main" thread to read objects from the queue. Like a delegate you can invoke. A standard solution to the producer/consumer problem. The .NET 4 BlockingCollection class makes it easy. Rewriting the thread code so it loops and stays responsive to worker requests is not always so easy.

creating and terminating a thread contained in a collection

I have a custom collection (a thread-safe ObservableQueue). I implemented the business logic inside the collection class (i.e. dequeue the items one by one and expose them to the outside). This is working fine. To prevent the collection from blocking the thread it is initialised in, the OnservableQueue implements a thread to perform that work. Now I am not perfectly sure of any pitfalls that could occur.
Is it a bad idea to initialise (not start! only initialise) the thread in the constructor? And what would be a good, if not best, practice of terminating the thread? Note, I dont need to know how to terminate a thread, that is working fine, I am rather interested in weather there is something wrong doing it using the disposable pattern or creating a method which would need to get called to terminate the thread. If implementing IDisposable are there any things I have to take in account regarding the collection/queue?
Edit: The thread is actually only pre-initialised to prevent NullReferenceException from being thrown in the Enqueue Method, where it is properly initilised again (the Enqueue Method is supposed to check weather a dequeuing thread is running already and if not to start a new one). Note that whenever all items are dequeued and the thread has done its work it will not be alive any longer either, so any time the queue is empty and a new item is added a new thread will get started to process the queue:
if (!_dequeuingThread.IsAlive)
{
// start the dequeuing thread
_dequeuingThread = new Thread(new ThreadStart(StartDequeuing));
_dequeuingThread.Name = "DeQueueThread";
_dequeuingThread.Start();
}
The if-statement does need an initialised thread. There are other possible ways of achieving this, but pre-initialising the thread seemed the least bothersome. You see that after checking weather the thread is alive, which it should not when being pre-initialised, it gets initialised again properly.
I don't see anything wrong with initialising in the constructor, but obviously bare in mind they will be initialised in a different thread than your worker thread.
As for stopping, I generally have a volatile boolean flag that the worker checks to keep running. If your worker thread sleeps at all, then have it wait on an event rather than sleeping, so you can wake it up immediately when stopping it.
There seems to be a problem with the fact that the consumer will initialize this collection object by calling its constructor and it would think that the object is initialized (that what the constructor is supposed to do), which is not correct as the initialization is happening on a separate thread created by the constructor. So, basically you need to implement some sort of "Asynchronous API on this object" to initialize this collection such that the consumer calls the initialize method (after creating the object using constructor) and then either by either passing a callback to the initialize method or by registering to an event on the collection object the consumer gets to know that the initialization has been completed.

WPF/threading: Dispatcher static vs Dispatcher on a control?

I'm a bit confused in terms of the dispatcher. Say I'm on a background thread doing some kind of long operation. I'd like to update the ui thread I understand I do this through the dispatcher. My question is, do i call the dispatcher statically like: Dispatcher.BeginInvoke(mywork) ... Or on the control i want to update: mytextbox.Dispatcher.BeginInvoke(mywork)
It's worth noting that calling Dispatcher.BeginInvoke isn't a static call: it's an implicit this.Dispatcher.BeginInvoke. If you can use this call, you're likely writing your code from within a control or window already. In that case, you're probably safe to call either since most of the time there will be one UI thread per application.
The actual static call would be Dispatcher.CurrentDispatcher.BeginInvoke, which is not something you want to call (see my comment on Hasan Khan's answer for why).
EDIT: Calling Application.Current.Dispatcher is not a bad thing. (And, for clarity, it's an instance property, not a static - being called on a static/singleton instance of Application.) This property will return the Dispatcher for the thread that the app was created with, and typically that's the thread that the UI is created on aswell - so Application.Current.Dispatcher returns the same Dispatcher as myWindow.Dispatcher would.
The static call Dispatcher.CurrentDispatcher (that I warned against) returns a Dispatcher for the thread you call it from. If you call it from a background thread, you'll get a new Dispatcher created especially for that thread - which often isn't what's wanted.
First I think it is important to understand, that the Dispatcher is not designed to handle big background operations. It is designed to queue work on the UI thread of an object. Here is a worthwhile MSDN article about the .NET threading model and Dispatcher:
Threading Model, Overview and the Dispatcher
Saying that the standard way of implementing the Dispatcher.BeginInvoke method would be to call it on the control:
startStopButton.Dispatcher.BeginInvoke(
DispatcherPriority.Normal, new NextPrimeDelegate(CheckNextNumber)
);
Hope that helps!
While in most cases using either DispatcherObject.Dispatcher (all dependency objects and controls inherit from DispatcherObject, among others) or Application.Current.Dispatcher is the right thing to do, as there's usually only one UI thread, there can be multiple UI threads and different windows can use different dispatchers. In that case, it's important to update the control using its dispatcher. It's stored in in its Dispatcher property (inherited from DispatcherObject), any other control in this window and the window itself.

Unreferenced Thread object dispose

If i use thread like this:
void foo()
{
new Thread().Start();
}
since the Thread object is not referenced, will it be disposed by GC before the designated work is done?
The thread should stay alive until its method(s) return.
Check out: What prevents a Thread in C# from being Collected?
From MSDN
It is not necessary to retain a
reference to a Thread object once you
have started the thread. The thread
continues to execute until the thread
procedure is complete.
The System.Threading.Thread class is really just there for bookkeeping/management. It isn't the actual mechanism that creates/maintains threads. That's managed by the runtime and is CLI implementation specific (for example, the Mono implementation may differ dramatically in thread management.)

Categories

Resources