I have an Exception Handling project in my application that can be called from anywhere to show the user there is a problem with with system. Everything works great when the call is made from somewhere in the UI as expected. When I make calls from no UI parts of the application everything freezes. I have the code wrapped in the thread safe calls and when stepping through they don't require the Invoke call. Any help is greatly appreciated. Code below:
Inside the form
void err_DispEvent(string text)
{
if (InvokeRequired)
{
Invoke(new Error.DisplayDelegate(err_DispEvent), new object [] {text});
}
else
{
this.Show();
}
}
Call from the class
public void FaultError(string errorMsg)
{
FaultForm fform = new FaultForm(errorMsg, "Internal Fault");
if (this.dispEvent != null)
{
dispEvent(errorMsg);
}
}
public event DisplayDelegate DispEvent
{
add { dispEvent += value; }
remove { dispEvent -= value; }
}
private event DisplayDelegate dispEvent;
public delegate void DisplayDelegate(string text);
Sample of how the class is used in the application
ECDUExceptions.Error newError = ECDUExceptions.Error.getInstance();
newError.FaultError("Heater is not responding to function calls, it has been turned off");
Some information when re-invoking methods:
Use BeginInvoke(...) instead of Invoke(...) as this will not wait for the call to finish, and so won't freeze the calling thread.
Use an Action when re-invoking. So in your case, you could change your invocation to:
BeginInvoke(new Action<string>(err_DispEvent), text);
Use BeginInvoke(...) instead of Invoke(...). THis will put your message request in the end of the queue
Create a queue of some sort for the messages that should be displayed.
Fill the queue from whatever thread you required.
From the GUI responsible for showing the messages, use timer to dequeue and show them.
Simplistic but will work effortlessly. And you won't need to Invoke() anything since Forms.Timer runs on UI message loop.
Related
UpDate1:
More detail: Thread 1 and 2 must be continuously active. Thread 1 is updating its GUI and doing HTTP POSTs. Thread 2 is using HTTPListener for incoming HTTP POSTs, and supplying that data to Thread 1. So the GUI needs to be display with current Textbox values and updated when Thread 2 supplies the data. Will Servy's or another approach allow both Threads to do their work concurrently? It appears the main thread waits for Thread 2 to complete it's work. It then takes the prepWork and does work with it. I coded in Servy's example but I couldn't find a definition for Run() with the Task class. It's library has no such method. I'm using Net 4.0 on VS 2010. Is there an equivalent method to use? Start() didn't compile either and I understand you can only run the Task once. Thanks for any additional assistance you can share.
Original Question:
I've tested code that will successfully kick off my event and update my GUI textbox in an event handler if the event is kicked off in what I understand as the UI Thread 1. When I attempt to call a Thread 1 method Fire() from my independent Thread 2 method PrepareDisplay(), Fire() is called and in turns fires off the event. I put in some Thread-safe call code (modeled from MSDN tutorial on Thread-Safety in WinForms), but the event handler still doesn't update the Textbox. When stepping thru the code, it appears that the InvokeRequired is false. My eventual goal is to pass data from Thread 2 to UI Thread 1 and update the Textboxes with the new data. I don't understand why the Thread-safe code isn't enabling this. Can someone help me understand this better, and what I have neglected? Below is the code:
Thank you very much,
namespace TstTxtBoxUpdate
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Aag_PrepDisplay aag_Prep1 = new Aag_PrepDisplay();
Thread AagPrepDisplayThread = new Thread(new ThreadStart(aag_Prep1.PrepareDisplay));
AagPrepDisplayThread.Start();
while(!AagPrepDisplayThread.IsAlive)
;
Thread.Sleep(1000);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new SetOperation());
}
}
}
namespace TstTxtBoxUpdate
{
// Thread 1: UI
public partial class SetOperation : Form
{
private string text;
public event Action<object> OnChDet;
delegate void SetTextCallback(string text);
private Thread demoThread = null;
public SetOperation()
{
InitializeComponent();
OnChDet += chDetDisplayHandler;
}
public void FireEvent(Aag_PrepDisplay aagPrep)
{
OnChDet(mName);
}
private void chDetDisplayHandler(object name)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
private void ThreadProcSafe()
{
this.SetText("402.5");
}
private void SetText(string text)
{
if(this.actFreqChan1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.actFreqChan1.Text = text;
}
}
}
}
namespace TstTxtBoxUpdate
{
// Thread 2: Data prepare
public class Aag_PrepDisplay
{
#region Fields
private Aag_PrepDisplay mAagPrep;
#endregion Fields
#region Properties
public Aag_PrepDisplay AagPrepDisp;
public Aag_PrepDisplay AagPrep
{
get { return mAagPrep; }
set { mAagPrep = value; }
}
#endregion Properties
#region Methods
public void PrepareDisplay()
{
mAagPrep = new Aag_PrepDisplay();
SetOperation setOp1 = new SetOperation();
setOp1.FireEvent(mAagPrep); // calls Thread 1 method that will fire the event
}
#endregion Methods
}
}
You're getting to the point of calling InvokeRequired when your main thread is still on Thread.Sleep. It hasn't even gotten to the point of creating a message loop yet (which is one in Application.Run) so there is no message loop for Invoke to marshal a call to.
There are all sorts of issues here. You're creating multiple instance of your form, one that you show, and an entirely different form that you're setting the text of. You clearly did not intend to do this; you want to have a single form that you're setting the text for.
Your main thread should not be doing a busywait until your first thread finishes. It likely shouldn't be there at all. If it weren't for the fact that your new thread is creating yet another new thread, the fact that your main thread is blocking until the second thread finishes and the second thread is trying to marshall a call to the main thread, it would normally deadlock. You shouldn't really be creating a second new thread here at all, but this is a case of two bugs "cancelling each other out". It prevents the deadlock, but both are still incorrect, and inhibit your ability to get to a working solution.
You also shouldn't have the Thread.Sleep in the main thread at all. I have no idea what purpose that's trying to achieve.
If you're goal is simply to start some long running work before showing the first form and then to update that form when you have your results, you're doing way more work than you need to do.
To do this we can have our form accept a Task in its constructor representing the completion of the long running work. It can add a continuation to that task to set a label, or a textbox, or do...whatever, with the results of that Task.
public class SetOperation : Form
{
private Label label;
public SetOperation(Task<string> prepWork)
{
prepWork.ContinueWith(t =>
{
label.Text = t.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
Then the main thread simply needs to start a new Task to do the given work in a thread pool thread and pass that in to our form:
[STAThread]
static void Main()
{
Task<string> prepWork = Task.Run(() => DoWork());
Application.Run(new SetOperation(prepWork));
}
private static string DoWork()
{
Thread.Sleep(1000);//placeholder for real work
return "hi";
}
And we're done. Note that DoWork should probably be in its own class designed for handling your business logic; it probably shouldn't be stuck into the Program class.
I have a Form which "listens" to events that are raised elsewhere (not on the Form itself, nor one of its child controls). Events are raised by objects which exist even after the Form is disposed, and may be raised in threads other than the one on which the Form handle was created, meaning I need to do an Invoke in the event handler (to show the change on the form, for example).
In the Dispose(bool) method of the form (overridden) I unsubscribed from all events that may still be subscribed when this method is called. However, Invoke is still called sometimes from one of the event handlers. I assume this is because the event handler gets called just a moment before the event is unsubscribed, then OS switches control to the dispose method which executes, and then returns control back to the handler which calls the Invoke method on a disposed object.
Locking the threads doesn't help because a call to Invoke will lock the calling thread until main thread processes the invoked method. This may never happen, because the main thread itself may be waiting for a release of the lock on the object that the Invoke-calling thread has taken, thus creating a deadlock.
So, in short, how do I correctly dispose of a Form, when it is subscribed to external events, which may be raised in different threads?
Here's how some key methods look at the moment. This approach is suffering the problems I described above, but I'm not sure how to correct them.
This is an event handler handling a change of Data part of the model:
private void updateData()
{
if (model != null && model.Data != null)
{
model.Data.SomeDataChanged -= new MyEventHandler(updateSomeData);
model.Data.SomeDataChanged += new MyEventHandler(updateSomeData);
}
updateSomeData();
}
This is an event handler which must make changes to the view:
private void updateSomeData()
{
if (this.InvokeRequired) this.myInvoke(new MethodInvoker(updateSomeData));
else
{
// do the necessary changes
}
}
And the myInvoke method:
private object myInvoke(Delegate method)
{
object res = null;
lock (lockObject)
{
if (!this.IsDisposed) res = this.Invoke(method);
}
return res;
}
My override of the Dispose(bool) method:
protected override void Dispose(bool disposing)
{
lock (lockObject)
{
if (disposing)
{
if (model != null)
{
if (model.Data != null)
{
model.Data.SomeDataChanged -= new MyEventHandler(updateSomeData);
}
// unsubscribe other events, omitted for brevity
}
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
}
Update (as per Alan's request):
I never explicitly call the Dispose method, I let that be done by the framework. The deadlock has so far only happened when the application is closed. Before I did the locking I sometimes got some exceptions thrown when a form was simply closed.
There are two approaches to consider. One is to have a locking object within the Form, and have the internal calls to Dispose and BeginInvoke calls occur within the lock; since neither Dispose nor BeginInvoke should take very long, code should never have to wait long for the lock.
The other approach is to just declare that because of design mistakes in Control.BeginInvoke/Form.BeginInvoke, those methods will sometimes throw an exception that cannot practically be prevented and should simply be swallowed in cases where it won't really matter whether or not the action occurs on a form which has been disposed anyway.
I'd like to provide a sort of addendum to supercat's answer that may be interesting.
Begin by making a CountdownEvent (we'll call it _invoke_counter) with an initial count of 1. This should be a member variable of the form (or control) itself:
private readonly CountdownEvent _invoke_counter = new CountdownEvent(1);
Wrap each use of Invoke/BeginInvoke as follows:
if(_invoke_counter.TryAddCount())
{
try
{
//code using Invoke/BeginInvoke goes here
}
finally { _invoke_counter.Signal(); }
}
Then in your Dispose you can do:
_invoke_counter.Signal();
_invoke_counter.Wait();
This also allows you to do a few other nice things. The CountdownEvent.Wait() function has an overload with a timeout. Perhaps you only want to wait a certain period of time to let the invoking functions finish before letting them die. You could also do something like Wait(100) in a loop with a DoEvents() to keep things responsive if you expect the Invokes to take a long time to finish. There's a lot of niftyness you can achieve with this method.
This should prevent any weird timing race condition type of issues and it's fairly simple to understand and implement. If anyone sees any glaring problems with this, I'd love to hear about them because I use this method in production software.
IMPORTANT: Make sure that the disposal code is on the Finalizer's thread (which it should be in a "natural" disposal). If you try to manually call the Dispose() method from the UI thread, it will deadlock because it will get stuck on the _invoke_counter.Wait(); and the Invokes won't run, etc.
I had the problem with the Invoke method while multithreading, and I found a solution that works like a charm!
I wanted to create a loop in a task that update a label on a form to do monitoring.
But when I closed the form window, my Invoke threw an exception because my Form is disposed !
Here is the pattern I implemented to resolve this problem:
class yourClass : Form
{
private bool isDisposed = false;
private CancellationTokenSource cts;
private bool stopTaskSignal = false;
public yourClass()
{
InitializeComponent();
this.FormClosing += (s, a) =>
{
cts.Cancel();
isDisposed = true;
if (!stopTaskSignal)
a.Cancel = true;
};
}
private void yourClass_Load(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task.Factory.StartNew(() =>
{
try
{
while (true)
{
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate { methodToInvoke(); });
}
}
}
catch (OperationCanceledException ex)
{
this.Invoke((MethodInvoker)delegate { stopTaskSignalAndDispose(); });
}
}, token);
}
public void stopTaskSignalAndDispose()
{
stopTaskSignal = true;
this.Dispose();
}
public void methodToInvoke()
{
if (isDisposed) return;
label_in_form.Text = "text";
}
}
I execute methodToInvoke() in an invoke to update the label from the form's thread.
When I close the window, the FormClosing event is called. I take this opportunity to cancel the closing of the window (a.Cancel) and to call the Cancel method of the object Task to stop the thread.
I then access the ThrowIfCancellationRequested() method which throws an OperationCanceledException allowing, juste after, to exit the loop and complete the task.
The Invoke method sends a "Window message" in a Queue.
Microsoft says : « For each thread that creates a window, the operating system creates a queue for window messages. »
So I call another method that will now really close the window but this time by using the Invoke method to make sure that this message will be the last of the Queue!
And then I close the window with the Dispose() method.
I am confused with scenario which I have encountered with cross thread access. Here is what I am trying to do:
Main UI thread - menu item click I create a background worker and run it asynchronously
private void actionSubMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem itemSelected = (ToolStripMenuItem)sender;
ExecuteTheActionSelected(itemSelected.Text);
}
The method ExecuteTheActionSelected is as follows:
private void ExecuteTheActionSelected(string actionSelected)
{
BackgroundWorker localBackgroundWorker = new BackgroundWorker();
localBackgroundWorker.DoWork += new DoWorkEventHandler(localBackgroundWorker_DoWork);
localBackgroundWorker.RunWorkerAsync(SynchronizationContext.Current);
}
The localBackgroundWorker_DoWork has:
ActionExecutionHelper actionExecutioner = new ActionExecutionHelper()
actionExecutioner.Execute();
The Execute method in that class that has method invoker which infact invokes the event handler in UI thread:
public void Execute()
{
// ---- CODE -----
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
}
protected virtual void ReadStdOut()
{
string str;
while ((str = executionProcess.StandardOutput.ReadLine()) != null)
{
object sender = new object();
DataReceivedEventArgs e = new DataReceivedEventArgs(str);
outputDataReceived.Invoke(sender, e);
//This delegate invokes UI event handler
}
}
The UI event handler is as follows:
private void executionProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (_dwExecuteAction != null)
{
_dwExecuteAction.ShowDataInExecutionWindow(e.Text);
}
}
Now here comes the cross thread issue:
public void ShowDataInExecutionWindow(string message)
{
if (rchtxtExecutionResults.InvokeRequired)
{
rchtxtExecutionResults.Invoke(new ShowDataExecutionDelegate(ShowDataInExecutionWindow), message);
}
else
{
this.rchtxtExecutionResults.AppendText(message + Environment.NewLine);
}
}
Here Invoke doesn't block the UI where as BeginInvoke blocks.
Please help me understand this scenario as i m confused a lot.
Yes, this is normal. The benefit you get out of Invoke() is that it blocks the worker thread. When you use BeginInvoke() the thread keeps motoring and issues invoke requests at a rate higher than the UI thread can handle. It depends on what you ask the UI thread to do but it starts to become a problem around 1000 invokes per second.
The UI thread stops being responsive in this scenario, it is constantly finding another invoke request back while it pumps the message loop and doesn't get around doing its regular duties anymore. Input and paint requests no longer get processed.
The clear source of the problem is the invoke request on every single line of output retrieved from the process. It is just generating them too quickly. You need to fix this by lowering the rate at which you invoke. There's a simple rule for that, you are only trying to keep a human occupied, invoking more than 25 times per second turns whatever you produce in but a blur to the eye. So buffer the lines and measure the amount of time that has passed since the last invoke call.
Also note that using Invoke() is an easy workaround but it isn't exactly guaranteed to work. It is a race, the worker thread could potentially always call the next Invoke() a wee bit earlier than the main thread re-entering the message loop and reading the next message. In which case you will still have the exact same problem.
I have a button on my windows form that calls the RunWorkerAsync() method, this in turn performs an action which then updates a ListBox on the same form.
After the DoWork event has finished I assign the Result for the event (Which is a list), I process the RunWorkerCompleted() event and then perform the following code to update my Listbox
which calls this:
(Apologies, code formatting won't work)
Now when I run the application and press the refresh button the following exception appears:
How would I get around this?
Edit:
The exception is thrown on the folowing statement, this occurs in the DoWork method where I clear the contents to keep the list up to date;
listBoxServers.Items.Clear();
You may not call Invoke on the list box, but on the form. For WinForms applications I use something like:
...
this.Invoke((MethodInvoker)delegate()
{
// Do stuff on ANY control on the form.
});
...
Depending on the .NET version, you may have to declare a delegate for MethodInvoker yourself as
public delegate void MethodInvoker();
However, you might also consider using the ReportProgress feature of the Background Worker. The respective event handler should be called in the context of the form's thread.
Here's a snippet which I find very handy:
public static void ThreadSafe(Action action)
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal,
new MethodInvoker(action));
}
You can pass it any delegate of Action type or simply a lambda like this:
ThreadSafe(() =>
{
[your code here]
});
or
ThreadSafe(listBoxServers.Items.Clear);
What I've done is something like this every time you need to run something across threads:
listBoxServers.BeginInvoke(
(Action)
(() => listBoxServers.Items.Clear()));
Background threads are not allowed to update the UI in Windows applications, so you have to revert the control back to the UI thread for the actual update.
Create a method that will call UpdateServerDetails on the main thread, like this:
private void DispatchServerDetails(List<ServerDetails> details)
{
Action<List<ServerDetails>> action = UpdateServerDetails;
Dispatcher.Invoke(action)
}
and then call DispatchServerDetails instead of UpdateServerDetails.
Some caveats:
-This works best in WPF applications, for WinForms, you'll need to jump through some hoops, or you can use InvokeRequired
-The UI update is still synchronous, so if UpdateServerDetails does a lot of work, it will block the UI thread (not your case, just to be on the safe side).
Using Invoke in a windows forms project can be a little tricky, there're some pitfalls that are documented but easy to miss. I recommend using something like you'll find in this question:
Is it appropriate to extend Control to provide consistently safe Invoke/BeginInvoke functionality?
It handles cases where invoke is not required, is called from different threads, handle is or isn't created, etcetcetc. It could be easily modified to be SafeInvoke() and SafeBeginInvoke() if you're not a fan of the bool parameter.
(Included here for your convenience:
/// Usage:
this.lblTimeDisplay.SafeInvoke(() => this.lblTimeDisplay.Text = this.task.Duration.ToString(), false);
// or
string taskName = string.Empty;
this.txtTaskName.SafeInvoke(() => taskName = this.txtTaskName.Text, true);
/// <summary>
/// Execute a method on the control's owning thread.
/// </summary>
/// <param name="uiElement">The control that is being updated.</param>
/// <param name="updater">The method that updates uiElement.</param>
/// <param name="forceSynchronous">True to force synchronous execution of
/// updater. False to allow asynchronous execution if the call is marshalled
/// from a non-GUI thread. If the method is called on the GUI thread,
/// execution is always synchronous.</param>
public static void SafeInvoke(this Control uiElement, Action updater, bool forceSynchronous)
{
if (uiElement == null)
{
throw new ArgumentNullException("uiElement");
}
if (uiElement.InvokeRequired)
{
if (forceSynchronous)
{
uiElement.Invoke((Action)delegate { SafeInvoke(uiElement, updater, forceSynchronous); });
}
else
{
uiElement.BeginInvoke((Action)delegate { SafeInvoke(uiElement, updater, forceSynchronous); });
}
}
else
{
if (!uiElement.IsHandleCreated)
{
// Do nothing if the handle isn't created already. The user's responsible
// for ensuring that the handle they give us exists.
return;
}
if (uiElement.IsDisposed)
{
throw new ObjectDisposedException("Control is already disposed.");
}
updater();
}
}
I just figured out a simpler way without using Invoke:
int fakepercentage = -1;
//some loop here......if no loop exists, just change the value to something else
if (fakepercentage == -1)
{
fakepercentage = -2;
}
else
{
fakepercentage = -1;
}
backgroundworker1.ReportProgress(fakepercentage);
Then in backgroundworker1_ProgressChanged(object sender, ProgressChangedEventArgs e):
if (e.ProgressPercentage < 0)
{
//access your ui control safely here
}
I have a windows forms program with a form MainForm. On a button press I start a code that runs (pulses) on every 0.5secs on another thread. I want to modify many things, like labels, progressbars on my MainForm, from the Pulse method. How is this possible?
So I would like to know, how to interract with variables, values, in that thread, and the MainForm. Modify each other, etc..
On foo button click, I tell my pulsator to start.
Pulsator.Initialize();
Here is the Pulsator class:
public static class Pulsator
{
private static Thread _worker;
public static void Initialize()
{
_worker = new Thread(Pulse);
_worker.IsBackground = true;
_worker.Start();
}
public static void Close()
{
if (_worker != null)
{
_worker.Abort();
while (_worker.IsAlive || _worker.ThreadState != ThreadState.Stopped)
{
//closing
}
}
}
public static void Pulse()
{
if (_worker != null)
{
while (true)
{
SomeOtherClass.Pulse();
Thread.Sleep(500);
}
}
else
{
SomeOtherClass.Pulse(); // yeah I know this doesnt needed
}
}
}
SomeOtherClass Pulse method looks like :
public static void Pulse()
{
//here I will have several values, variables, and I want to show results,
// values on my MainForm, like:
Random random = new Random();
MainForm.label1.Text = random.Next(123,321).ToString(); // I hope you know what I mean
}
Of course it's much complicated, it's just a silly example.
Generally, in WinForms it's not safe to modify the state of visual controls outside the thread that owns the control's underlying unmanaged resources (window handle). You have to use the Control.Invoke method to schedule executing the modification on the control's owning thread.
As others already mentioned, you have to use Control.Invoke to change the UI controls from the background thread.
Another option is to use System.ComponentModel.BackgroundWorker (it's available in the form designer toolbox). You could then take a regular forms timer, to call the RunWorkerAsync-Method and do your background work in the DoWork event handler, which is automatically called from another thread.
From there, you can hand data back to the main thread, by calling ReportProgress. This will raise the ProgressChanged event in the main thread, where you are free to update all your UI controls.
Why not use a System.Timers.Timer?
E.g.:
trainPassageTimer = new Timer(500);
trainPassageTimer.AutoReset = true;
trainPassageTimer.Elapsed += TimeElapsed;
...
private void TimeElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
// Do stuff
// Remember to use BeginInvoke or Invoke to access Windows.Forms controls
}
C# 2 or higher (VS2005) has anonymous delegates (and C# 3 has lambdas which are a slightly neater version of the same idea).
These allow a thread to be started with a function that can "see" variables in the surrounding scope. So there is no need to explicitly pass it anything. On the downside, there is the danger that the thread will accidentally depend on something that it should not (e.g. a variable that is changing in other threads).
_worker = new Thread(delegate
{
// can refer to variables in enclosing scope(s).
});