this.Close() not killing thread created by observer NewThreadScheduler.Default.Schedule - c#

I'm pretty new to C# and I'm having the following problem: I have a WPF application that executes an infinite task which performs some pretty expensive background operations. Those operations can occasionally change a value and it has to be updated in the UI. The operations need to run in a thread different than the UI thread, since they could lock the UI. So, I'm trying to use the System.Reactive library and it's actually working pretty well... but, when I try to close the application by using a custom close button that executes the this.Close(); method, the app is not being closed.
My observable looks something like this:
internal IObservable<string> DoBackgroundOperations(string param) {
return Observable.Create<string>(o => {
NewThreadScheduler.Default.Schedule(() => {
for (;;) {
param = // some operations that change the param
// when the param has been changed, I send the new value to the subscribers
o.OnNext(param);
}
});
return Disposable.Empty;
});
}
Then I'm subscribing to it and changing the value I need to update in the UI:
sevice.DoBackgroundOperations(param).Subscribe(newVal => Data = newVal);
As I said before, I'm receiving the updated values when they come and it's working well, but when the click event of the close button is triggered, the UI window "disappears" but the application itself is never being closed. I think the thread created by the observable is keeping the app alive.
So, my question is: how can I properly close the app and prevent the thread from keeping it alive?
Thanks!
Edit
I'm using caliburn.micro for implementing the MVVM pattern. I'm doing the subscription in one of my ViewModel classes. I don't think it matters, but just in case...

Do not ever return Disposable.Empty. You're forced to do that because your code doesn't have a natural disposable in turn because you create an infinite loop.
Get rid of the infinite loop and you can make the whole problem go away.
You could solve this simply by this:
internal IObservable<string> DoBackgroundOperations(string param)
{
return
Observable
.Generate(
0,
x => true,
x => x + 1,
x => /* some operations that change the param */,
Scheduler.Default);
}
I purposely chose Scheduler.Default because Scheduler.NewThread has been deprecated.
Had you provided the code for // some operations that change the param I could have given you working code.
Now, to close your app cleanly you should dispose of any subscriptions you create, but at least you'd no longer be tying up a thread in an infinite loop.

Related

Invoke not switching back to separate thread

I have the method below that is running on a separate thread from the main UI thread, and I am trying to update the ListBox control on the main thread. The code does work and the field does get updated, but when the Invoke method runs it switches to the main thread. The problem is that the code after the Invoke also runs on the main thread, but I need it to run on the separate thread.
public static void Status_Message(string str, int destination, int prompt)
{
//Clear_System_Message_Area();
sysmsg++;
ListBox tl = Application.OpenForms["GMLEC"].Controls["groupBox2"].Controls["TestList"] as ListBox;
if (!tl.InvokeRequired)
{
tl.Items.Add(str);
tl.Refresh();
}
else
{
tl.Invoke(new Action<string, int, int>(Status_Message), str, destination, prompt);
}
if (destination == 1)
{
Printer.Output(str);
}
if (prompt == 1)
{
Pause(false);
}
if (sysmsg > 23)
{
Pause(true);
}
}
Is there a way to make it go back to the separate thread?
If you don't want code run on the UI thread, don't invoke the method that contains it.
For what it's worth, I disagree with any code that uses InvokeRequired. First of all, you ought to know from the context whether invoke is required or not. If you don't know which thread the code that's executing is on, then there is too much coupling between the UI and background task parts of the code.
But secondly, the Control.Invoke() method has to check which thread is current anyway, because it has to work whether you are on the UI thread or not. You can always call it safely from the UI thread, and when you do, it can't go queueing up your delegate for invocation and then waiting for it, because that would deadlock. It has to just invoke the delegate directly, but only in that case, which means it's doing the InvokeRequired check anyway.
So, taking all of that into account, just write your code to always invoke the part that needs invoking, and be done with it.
For example:
public static void Status_Message(string str, int destination, int prompt)
{
//Clear_System_Message_Area();
sysmsg++;
ListBox tl = Application.OpenForms["GMLEC"].Controls["groupBox2"].Controls["TestList"] as ListBox;
tl.Invoke((MethodInvoker)(() =>
{
tl.Items.Add(str);
tl.Refresh();
}));
if (destination == 1)
{
Printer.Output(str);
}
if (prompt == 1)
{
Pause(false);
}
if (sysmsg > 23)
{
Pause(true);
}
}
Now, some other notes about this:
It's doubtful that you should be calling Refresh(). Let Winforms deal with updating on its own. If you've somehow interfered with it refreshing the window normally, fix that. Don't hack around it by calling Refresh() yourself.
It's almost certain that there's a better way to encapsulate the ListBox object than by always looking it up from the top of the UI control graph. For example, maybe the actual object should have been referenced directly (e.g. from a TestList field) and passed to the code that will eventually need it.
Finally, and most important, the fact that you're using Invoke() at all is a big warning flag in modern code. There's a decent chance that your overall code could be refactored to use async/await in a way that allows it to read more naturally and still work correctly, but at the very least it would be better to use Progress<T> to mediate cross-thread updates like this.
To address any of these issues would be beyond the scope of the current question, but I do encourage you to take the suggestions under consideration.
This might help...
normally I use Invoke() to activate a part of the script after a certain time. Invoke() Does NOT repeat, if you want it to repeat you can use InvokeRepeating().
another option is to use "Multi-Threading". Here's how to use Multi-Threading:
using System.Threading
public static Thread newThread = new Thread(MultiThread)
private void Start()
{
newThread.Start()
//also newThread.Abort() to quit the thread
}
private static void MultiThread()
{
// this is the seporate thread
// i normally use this for a "while (True)" loop cause it will stop responding
//otherwise
}
srry for any typos
Hopefully this helps

Prevent multiple execution of a ReactiveCommand (CreateAsyncTask)

Is it possible to prevent multiple execution of a ReactiveCommand.
Here is the 'simple' code I use:
The command is created:
this.LoadCommand = ReactiveCommand.CreateAsyncTask(
async _ => await this._dataService.Load(),
RxApp.TaskpoolScheduler);
After I add the subscription to the command:
this.LoadCommand.Subscribe(assets => ...);
And finally, I execute the command:
this.LoadCommand.ExecuteAsyncTask();
If I call the ExecuteAsyncTask multiple time at several location, I would like that any subsequent calls wait for the first one to finish.
EDIT:
Here is the complete code for the Subscribe method:
this.LoadCommand.Subscribe(assets =>
{
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background,
new Action(() => this.Assets.Clear()));
foreach (Asset asset in assets)
{
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background,
new Action<Asset>(a =>
{
this.Assets.Add(a);
}), asset);
}
});
Thanks,
Adrien.
I downloaded your sample application, and was able to fix it. Here's my 2 cents:
1) I took out the Rx.TaskpoolScheduler parameter in your command creation. That tells it to deliver the results using that scheduler, and I think you want to stick to delivering results on the UI thread.
2) Since by making this change you are now running your Subscribe logic on the UI thread, you don't need to deal with all that Invoking. You can access the collection directly:
this.LoadCommand.Subscribe(dataCollection =>
{
DataCollection.Clear();
DataCollection.AddRange(dataCollection);
});
Making just those 2 changes caused it to "work".
I'm no expert, but what I think was happening is that the actual ReactiveCommand "LoadCommand" you had was immediately returning and delivering results on various TaskPool threads. So it would never allow concurrency within the Command itself, which is by design. However the subscribes, I think since each was coming in on a different thread, were happening concurrently (race). So all the clears occurred, then all the adds.
By subscribing and handling all on the same thread you can avoid this, and if you can manage it on the UI thread, you won't need to involve Invoking to the Dispatcher.
Also, in this particular situation using the Invoke on the Dispatcher with the priority DispatcherPriority.Background seems to execute things in a non-serial fashion, not sure exactly the order, but it seemed to do all the clears, then the adds in reverse order (I incremented them so I could tell which invocation it was). So there is definitely something to be said for that. FWIW changing the priority to DispatcherPriority.Send kept it serial and displayed the "expected" behavior. That being said, I still prefer avoiding Invoking to the Dispatcher altogether, if you can.

Threadpool - How to call a method (with params) in the main thread from a worker thread

I'm working through my first attempt to thread an application. The app works with a large data set that is split up into manageable chunks which are stored on disk, so the entire data set never has to reside in memory all at once. Instead, a subset of the data can be loaded piecemeal as needed. These chunks were previously being loaded one after the other in the main thread. Of course, this would effectively pause all GUI and other operation until the data was fully loaded.
So I decided to look into threading, and do my loading while the app continues to function normally. I was able to get the basic concept working with a ThreadPool by doing something along the lines of the pseudo-code below:
public class MyApp
{
List<int> listOfIndiciesToBeLoaded; //This list gets updated based on user input
Dictionary<int,Stuff> loadedStuff = new Dictionary<int,Stuff>();
//The main thread queues items to be loaded by the ThreadPool
void QueueUpLoads()
{
foreach(int index in listOfIndiciesToBeLoaded)
{
if(!loadedStuff.ContainsKey(index))
loadedStuff.Add(index,new Stuff());
LoadInfo loadInfo = new LoadInfo(index);
ThreadPool.QueueUserWorkItem(LoadStuff, loadInfo);
}
}
//LoadStuff is called from the worker threads
public void LoadStuff(System.Object loadInfoObject)
{
LoadInfo loadInfo = loadInfoObject as LoadInfo;
int index = loadInfo.index;
int[] loadedValues = LoadValuesAtIndex(index); /* here I do my loading and ...*/
//Then I put the loaded data in the corresponding entry in the dictionary
loadedStuff[index].values = loadedValues;
//Now it is accessible from the main thread and it is flagged as loaded
loadedStuff[index].loaded = true;
}
}
public class Stuff
{
//As an example lets say the data being loaded is an array of ints
int[] values;
bool loaded = false;
}
//a class derived from System.Object to be passed via ThreadPool.QueueUserWorkItem
public class LoadInfo : System.Object
{
public int index;
public LoadInfo(int index)
{
this.index = index;
}
}
This is very primitive compared to the quite involved examples I've come across while trying to learn this stuff in the past few days. Sure, it loads the data concurrently and stuffs it into a dictionary accessible from the main thread, but it also leaves me with a crucial problem. I need the main thread to be notified when an item is loaded and which item it is so that the new data can be processed and displayed. Ideally, I'd like to have each completed load call a function on the main thread and provide it the index and newly loaded data as parameters. I understand that I can't just call functions on the main thread from multiple other threads running concurrently. They have to be queued up in some way for the main thread to run them when it is not doing something else. But this is where my current understanding of thread communication falls off.
I've read over a few in-depth explanations of how events and delegates can be set up using Control.Invoke(delegate) when working with Windows Forms. But I'm not working with Windows Forms and haven't been able to apply these ideas. I suppose I need a more universal approach that doesn't depend on the Control class. If you do respond, please be detailed and maybe use some of the naming in my pseudo-code. That way it will be easier for me to follow. Threading appears to be a pretty deep topic, and I'm just coming to grips with the basics. Also please feel free to make suggestions on how I can refine my question to be more clear.
If you aren't using a GUI framework with some kind of dispatcher or GUI thread (like WPF or WinForms) then you'll have to do this manually.
One way to do this is to use a SynchronizationContext.
It's somewhat tricky to manage but there are a few articles which go into how it works and how can you make your own:
http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I
http://www.codeproject.com/Articles/32113/Understanding-SynchronizationContext-Part-II
However I would also consider using either a single 'DictionaryChanged' boolean which is regularly checked by your 'main thread' (when it is idle) to indicate that the dictionary is changed. The flag could then be reset on the main thread to indicate that this has been handled. Keep in mind that you'll need to do some locking there.
You could also queue messages using a thread safe queue which is written by the background thread and read from the main thread if a simple variable is not sufficient. This is essentially what most dispatcher implementations are actually doing under the hood.

How can a function be triggered with an event?

I have an application wherein I would like a function to be executed in the same thread when an event is fired. For example:
SomeCode()
{
// Do something...
// Fire event to run SomeOtherCode().
}
SomeOtherCode()
{
// Do something else...
}
I do not want to simply call the function because it will hold things up. SomeOtherFuction() needs to be executed in the same thread because it needs to access the form controls, and I need it to begin execution from an event trigger firing. I am using Microsoft Visual C# 2008 Express Edition. Thanks.
::: EDIT:::
Additional Details: The bottom line is that the contrustor of my form application is taking far too long to complete, and it is causing a significant delay, from when the user launches the application to when the application window appears on the display. This is not a problem on faster computers, but on slower computers it is a big problem. I need to exit the contrustor as soon as possible, thus allowing the framework to draw the application window, and continue initialization outside the constructor. (All essential items would still be initialized inside the constructor.)
An event-triggered function call would be ideal. I would prefer not to use a timer. Interlacing the affected code with Invokes is impractical in my situation and would require much more time to implement than I have to work on this. A simple example of an event-driven function call is all I'm really looking for. Thanks.
From your posts it's seems like you're confusing a few issues. The standard pattern in .Net is for events to run synchronously. The following lines are essentially identical in terms of when they execute.
Option #1
SomeCode();
SomeOtherCode();
Option #2
SomeEvent += delegate { SomeOtherCode(); }
...
SomeCode();
SomeEvent(this,EventArgs.Empty);
If you want to unblock the UI thread and run the code later you'll need to use some mechanism to delay the running of the SomeOtherCode function. The easiest way to do this in a WinForms application is to use a WinForms Timer instance. This will raise an event on the UI thread at a later point in time that you can respond to. It also won't block the UI thread during this time allowing your form to continue processing.
You seem to be asking to run SomeOtherCode() later.
You can call BeginInvoke (either from the UI thread or from any other thread) to queue a function to run during the next message loop:
BeginInvoke(new Action(SomeOtherCode));
It seems that you would want to add an event to the class that exposes the SomeCode method. Then, the class that implements the SomeOtherCode method would attach an event handler that calls the SomeOtherCode method.
It's completely viable to have this done in one class, in case you have some sort of state model where you want to add/remove the call depending on some other logic.
I think you want to put SomeOtherCode into a Task or BackgroundWorker, which would then synchronize with the UI thread to send it updates.
I recently posted on my blog a class that makes updating the UI from a Task as easy as from a BGW. I do recommend using Task rather than BackgroundWorker.
Simialr to what Stephen said, I would recommend that you move as much of that initialization code to a background thread or task. Let the background thread do as much work as possible, then send the necessary window updates to your UI thread via Action<>'s. Here's some quick psuedo-sample code:
protected void LoadMyListInBackground(object state)
{
List<string> myList = Databse.FetchMyList(myParameters); // This take a while, so the UI thread isn't waiting
ShowMyList(myList);
}
protected void ShowMyList(List<string> theList)
{
if(InvokeRequired)
Invoke(new Action<List<string>>(ShowMyList, theList);
else
{
foreach(string item in theList)
myListBox.Items.Add(item);
}
}
In this example the UI thread is free to keep drawing your window while the background thread does the lengthy database work. The problem is, even if you fire an event outside of your constructor, and that event occurs on the UI thread and takes a long time, the user might see the window but that window is going to 'freeze' and possibly appear to be 'crashed' to the user. This technique prevents that and provides a better user experience.

Force event handler to run on object's thread, C# .NET

I have a class that handles events created by multiple member objects. Events from these objects spawn worker threads for the event, so that the various event handlers in my class are running on different threads (one is a serial handler, one is a timer event, etc.) I'm looking for a simple way to make my code thread-safe, preferably by forcing the event handlers to run on my object's thread.
If this were a Forms UI object, I could take advantage of its implementation of the ISynchronizeInvoke interface, and make calls to InvokeRequired, Invoke, etc. In WPF I could use a Dispatcher object. But my class needs to run *independently of any UI code.
Here's a simplified example of what I have:
public class MyClass
{
private SomeObject object1;
private AnotherObject object2;
public MyClass()
{
object1 = new SomeObject();
object2 = new AnotherObject();
object1.AThreadedEvent += ThreadedEventHandler1;
object2.AnotherThreadedEvent += ThreadedEventHandler2;
}
// This runs in its own thread!
private void ThreadedEventHandler1()
{
// DO STUFF HERE
}
// This runs in its own thread!
private void ThreadedEventHandler2()
{
// DO STUFF HERE
}
}
Because both event handlers access the same objects in the parent class (including each-other!), it would be awesome if there were a simple way to force the event handlers to run in the creating object's thread.
I've toyed with the idea of having my class implement the ISynchronizeInvoke interface, but it appears that doing so can get pretty complicated. Before I jump down that rabbit hole, I thought I'd ping the experts to see if there is a more simple solution.
Thoughts?
EDIT:
Part of the reason I want to run the event handlers in the parent object's thread is because the parent object has it's *own events that are triggered based on the events sent by its member objects. I'd like any threading functionality to be hidden by this class, so that code that uses the class doesn't have to worry about thread-related issues (ie. locks and so on). Simply locking shared data won't do the job, because I *still need to trigger events from within the threaded event handlers.
The ideea of invoking on another thread is hand to hand with having a while loop that from time to time it checks whether there is an "outside" message to be processed. For UI, there is the windows loop that does that. For an external thread, you must write manually a loop. Imagine a situation without a loop and that you have a relative long running thread right ? and sudently you want to interrupt this thread to invoke your message and resume what it was doing ON THE SAME shared stack memory. This interruption would destroy your stack. This is simply NOT possible. The other possibility is to use a synchronization mechanism such as ManualResetEvent and just wait for a signal (a signal that comes outside your thread). So, to resume, in order to process a message from another thread, you basically have only two options:
1) You have a while loop, eventually using a little sleep (to give some time / ticks to other threads to do their job)
while (true) {
Thread.Sleep (5);
if (someMessageArrived) { ... }
}
2) You just wait for a message implementing somehow the producer / consummer architecture:
On listening thread:
aManualResetEvent.WaitOne ();
On the "producer" thread:
aManualResetEvent.Set ();
There are advanced classes in .NET framework that might help such as BlockingCollection.
Hope this helps
Assumming, that your class runs in its own thread that the only logic is to execute the incomming calls from other threads, this would be the solution:
(comments inside)
public class MyClass
{
private SomeObject object1;
private AnotherObject object2;
public MyClass()
{
object1 = new SomeObject();
object2 = new AnotherObject();
object1.AThreadedEvent += ThreadedEventHandler1;
object2.AnotherThreadedEvent += ThreadedEventHandler2;
}
// This runs in its own thread!
// Only add the real function call to the queue
public void ThreadedEventHandler1()
{
tasks.Add(ThreadedEventHandler1_really);
}
private void ThreadedEventHandler1_really()
{
// DO STUFF HERE
}
// This runs in its own thread!
// Only add the real function call to the queue
public void ThreadedEventHandler2()
{
tasks.Add(ThreadedEventHandler2_really);
}
// here is the actual logic of your function
private void ThreadedEventHandler2_really()
{
// DO STUFF HERE
}
// the queue of the tasks
BlockingCollection<Action> tasks = new BlockingCollection<Action>();
// this method never returns, it is blocked forever
// and the only purpose of i is to do the functions calls when they added to the queue
// it is done in the thread of this instance
public void StartConsume()
{
foreach (Action action in tasks.GetConsumingEnumerable())
{
// add logic before call
action();
// add logic after call
}
}
}
The solution based on that the caller threads tat calls the functions: ThreadedEventHandler1 and ThreadedEventHandler2, actually add the real call to the queue and emediately continue with their run.
From the other hand, StartConsume function iterates the queue and makes the calls of the added method calls. If you want to add another logic before and after call, you can add it in this function.
Hope it helped to achieve your goal.
Without completely understanding the rational behind your design. I can say that the problem you are trying to solve was solved many times before.
I will assume your main object is like a service which expects calls (in this case events) from itself and other services (the sub objects). If you would think about it in terms of services (which you arguably should) WCF solves that problem for you doing all the heavy lifting #Rami suggested.
You define the main service with the following behavior:
Instance Context Mode - Single
Concurrency Mode - Single
More about these here.
And every event handler would call that main service notifying it about the event.
I am pretty sure you would not go that far and implement every class as a service, but thought it is worth offering anyway as an option.
OK, based on all of your feedback (thanks!) I have a solution to my problem. The short answer: what I wanted to do isn't possible.
Here are more details for those who asked. I'm writing a DLL that manages a device attached to a serial port. This includes basic serial port COM (packet TX and RX, including parsing), and higher-level protocol behavior (TX, Ack, retry on timeout, etc.) The serial port event handlers provided by .NET are obviously asynchronous, as are the System.Timers.Timer objects that I use to handle timeouts, etc.
I am building the code around an MVVM architecture, so that my UI doesn't have any logic in it whatsoever. Hence my need to avoid exploiting Dispatcher or Invoke functionality provided by the UI.
What I was looking for was a way to handle asynchronous events within my DLL in the same simple manner provided by WinForms and WPF. But as has been pointed out, and as I learned when digging deeper, what you are *really doing when you call BeginInvoke or a Dispatcher is pushing something onto a queue, to be consumed later by a different thread polling the queue. Outside the context of a UI, no such polling architecture exists.
SO. My options are to lock the shared objects in my class to make it thread safe, or to implement my own polling architecture within another thread (to avoid blocking the program that uses the DLL) that emulates what the UI code already does.
In either case, the UI code will still need to use its Invoke or equivalent tools when handling events from the DLL class. I suppose that's OK.

Categories

Resources