Invoke not switching back to separate thread - c#

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

Related

invoke during background worker

I need to invoke this: string input_ip_r = listView1.Items[lc].SubItems[1].Text;
so I used
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(function));
return;
}
This worked but now I have put it into a BackgroundWorker and using this
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(bw.RunWorkerAsync));
return;
}
it gives an error that you can only run BackgroundWorker one at a time.
So how do I invoke while in the Backgroundworker?
1) Don't put RunWorkerAsync as the method to invoke. It's not actually running the method that you think. What you should really put there is something like this:
this.Invoke(new MethodInvoker(MethodToUpdateUI));
MethodToUpdateUI should be some new method that you create that specifically does whatever UI updates should be made in this context.
2) There's no need for InvokeRequired. You're in a background thread. Invoking will always be required.
To be honest, the entire patter of if(invoke required) call myself else do stuff is an odd construct which I dislike. InvokeRequired should pretty rarely be used. You should almost always know whether you're in the UI thread or a background thread, if you don't, chances are something wrong (either you're always in one or the other and you just don't know which, or it shouldn't be non-deterministic). Usually this means having methods that must be run in the UI thread. If you're already in the UI thread you just call them, if you're in a background thread and know it then you call Invoke first.
On top of that, Invoke works just fine even if you call it when you're already in the UI thread, so there's really no significant negative consequences to just calling Invoke regardless of whether you're in a background thread or already in the UI thread.
3) Usually it's best to separate code for solving business problems from UI code. It's code smell to be invoking from within DoWork's handler. If this is right near the end, you should probably be adding an event handler to RunWorkerCompleted. If you're calling this periodically to update the UI with progress of the worker, you should be using ReportProgress and handling the ProgressReported event. For getting info from the UI for use in a long running task you should access it before starting the background task. For exceptional cases that aren't any of those, it may be appropriate to use Invoke, but the remaining cases ought to be rare.
I'm not quite sure how you want to use the values, but just to give you an example, you could easily just do this in the BackgroundWorker thread:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string input_ip_r = "";
this.Invoke(new Action(() =>
{
// Don't know what "lc" is (a loop variable?)
input_ip_r = listView1.Items[lc].SubItems[1].Text;
}));
}
See this answer for other ways of doing the same (this is for >= .Net 3.5)

Why do I not get the "Cross-thread operation not valid" error

I use a BackgroundWorker and do this:
private void loadNewAsyncToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Text = "RunWorkerAsync()";
backgroundWorkerLoading.RunWorkerAsync();
}
private void backgroundWorkerLoading_DoWork(object sender, DoWorkEventArgs e)
{
UnsafeThreadMethod("hello");
EvenUnsaferThreadMethod();
}
And now the two methods.
private void UnsafeThreadMethod(string text)
{
toolStripLabelRssFeedData.Text = text;
}
private void EvenUnsaferThreadMethod()
{
panelLoading.Visible = true;
}
I don't understand why UnsafeThreadMethod doesn't throw the following exception but EvenUnsaferThreadMethod does.
Cross-thread operation not valid: Control 'panelLoading' accessed from a thread other than the > thread it was created on.
According to the message it's because toolStripLabelRssFeedData was created on the same thread but it wasn't.
I thought that I can't call controls created by the main thread and have to use the ProgressChanged event. What's going on?
And I have a second question. What is the advantage of doing it like this when I can use ProgressChanged? What should I do?
private void EvenUnsaferThreadMethod()
{
if (panelLoading.InvokeRequired)
{
panelLoading.Invoke(new MethodInvoker(() => { EvenUnsaferThreadMethod(); }));
}
else
{
panelLoading.Visible = true;
}
}
To the first question:
the cross-thread exception is deliberately thrown in Debug mode. This means there is (conditional) code checking on InvokeRequired built into most of the GUI controls. Like the Panel.
Apparently the ToolstripLabel does not make this check. Since it does not derive from Control that could be because it is outside the scope of this safety net.
Since the standard disclaimer "Any instance members are not guaranteed to be thread safe" applies to the ToolstripLabel I would just go with the normal InvokeRequired logic when setting the Text.
For your first question, I am not entirely sure, but a review from online seems to show that sometimes this will not throw an exception, but it will not update the label. Is that the case here? Is your label being updated along with having no exception?
However, I can answer you second question right now. The ProgressChanged event is meant for exactly what it sounds like. It is supposed to be called to let the UI thread know the status of the backgroundworker so that it can update itself appropriately. The original calling thread (UI in this case) is the one that is used for the ProgressChanged, so when it updates it does not need to call Invoke. But, this should really only be done for showing the progress of a background worker.
Now, if it is not an update that you are trying to pass to the calling method, then I would suggest just passing your return data back through the RunWorkerCompleted event. This passes all of your final data back up to the original (UI) thread, so that it can update the UI without any need for an Invoke.
So, yes your call to Invoke will work, though. However, understanding what each of the other events are for can help you understand why to use one way over another. Maybe a ProgressChanged event fits better? It can also declutter your code from having unnecessary invokes.
Update to first q
I still cannot find anything about the toolstrip not needing the invoke. In fact I am finding the opposite using google searches like "toolstriplabel no cross thread exception" or "toolstriplabel invoke", etc. However, as henk mentioned, the toolstriplabel doesn't inherit from control so that might explain why no invoke is required. However, my suggestion is to assume that it will act like any other UI control and make sure it is updated on the UI thread to be safe. do not rely on quirks. Better safe than sorry, you never know if things like this might change, especially since it is logically a UI item to most..,
The advantage of your second choice is that it works :)
All UI elements are created on main UI thread and, what is more important from this question perspective, is that can be acessed only within that thread.
This is the reason why your first case fails and that is the reason your second case will work. Invoke()... will redirect required merhod call to the main UI thread.
Hope this helps.

How come I don't need an invoke for some form elements a non-GUI thread?

I have a BackgroundWorker that calls a function on a non-GUI thread. I've noticed that for some form elements I can get away with updating the GUI without doing the invoke. Others will still result in a runtime error because the program attempted to update the GUI in a non-threadsafe way.
Why is that?
You've probably stumbled upon some methods or properties that don't check context and throw an exception. That doesn't mean it is a good idea to do so. Infact, I would avoid it at any cost.
Update:
Assuming WinForms here.
If you think it is too cumbersome to invoke, use an extension method:
public static class ControlExtensions
{
public static void Do(this Control c, Action f)
{
if (c.InvokeRequired)
{
c.Invoke(f);
}
else
{
f();
}
}
}
Then, in DoWork of BackgroundWorker:
// Background work here
this.Do(() =>
{
// This runs on UI thread
});
I find this a lot easier to use than BackgroundWorkers ReportProgress.
Not all gui elements and their methods are translated to WM_something. There are methods that work directly not using message queue at all. Therefore, they are safe to use from any thread.

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.

Any solution to Illegal Cross Thread Operation exception?

When you data bind in C#, the thread that changes the data causes the control to change too. But if this thread is not the one on which the control was created, you'll get an Illegal Cross Thread Operation exception.
Is there anyway to prevent this?
You should be able to do something like:
if (control.InvokeRequired)
{
control.Invoke(delegateWithMyCode);
}
else
{
delegateWithMyCode();
}
InvokeRequired is a property on Controls to see if you are on the correct thread, then Invoke will invoke the delegate on the correct thread.
UPDATE: Actually, at my last job we did something like this:
private void SomeEventHandler(Object someParam)
{
if (this.InvokeRequired)
{
this.Invoke(new SomeEventHandlerDelegate(SomeEventHandler), someParam);
}
// Regular handling code
}
which removes the need for the else block and kind of tightens up the code.
As I don't have a test case to go from I can't guarantee this solution, but it seems to me that a scenario similar to the one used to update progress bars in different threads (use a delegate) would be suitable here.
public delegate void DataBindDelegate();
public DataBindDelegate BindData = new DataBindDelegate(DoDataBind);
public void DoDataBind()
{
DataBind();
}
If the data binding needs to be done by a particular thread, then let that thread do the work!
If the thread call is "illegal" (i.e. the DataBind call affects controls that were not created in the thread it is being called from) then you need to create a delegate so that even if the decision / preparation for the DataBind is not done in the control-creating thread, any resultant modification of them (i.e. DataBind()) will be.
You would call my code from the worker thread like so:
this.BindData.Invoke();
This would then cause the original thread to do the binding, which (presuming it is the thread that created the controls) should work.
In WPF and Silverlight the binding infrastructure takes care of the switching to the UI thread.

Categories

Resources