Control.InvokeRequired - Subject to a race condition - c#

I found a suggested solution to the cross-thread exception issue in another posting and have used it my code below, but I am finding it erratic at best. My tests indicate that it's correct operation is at the mercy of a race condition so I was hoping someone might be able to point out the obvious or provide a more robust solution.
I have a program with two simple forms, where the sole purpose of Form1 is to open Form2. Form2 only contains a RichTextBox and has code that starts a thread that accesses that RichTextBox in an arbitrary way. When execution reaches the InvokeRequired property it is usually (but not always) false, so it goes directly to the RichTextBox access where a cross-thread exception is generated. However, when I call Thread.Sleep(...) just before testing the InvokeRequired property it appears to work properly. However, I hate to use Sleep for this purpose simply because it seems like a kluge that may not always work. Is there a reliable, yet reasonable, way to do cross-thread communication? Thanks.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var form2 = new Form2();
form2.ShowDialog();
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
Thread myThread = new Thread(new ThreadStart(myStartingMethod));
myThread.Start();
}
void myStartingMethod()
{
Test("Hello world!\n");
}
private delegate void myCallback(string text);
private void Test(string text)
{
// If I put Thread.Sleep(...something...) here it works better.
if (myRichTextBox.InvokeRequired)
{
myCallback d = new myCallback(Test);
Invoke(d, new Object[] { text });
}
else
{
// Cross-thread exception usually occurs, but not always.
int x = myRichTextBox.TextLength;
}
}
}

Related

Change WinForms using Threads in C#

I'm trying to change Forms using threads. Initially I used Hide() and Show() to hide the previous Form from the next one, the problem is that when I close the application there is always something running in the backgorund. My idea is this: From Form1 clicking a button goes to Form2 which in turn can choose whether to return to Form1 or go to Form3 which in turn can choose whether to return to Form2 or Form1
This is a piece of code from the Form1 button that if clicked must take me to Form2. The point is that it does not close Form1 and in fact it always remains in the background and when I click the button to close Form2 (using Close ()) the program does not close and remains at Form1 and if I close that then the program closes definitively
The second form is called OptionGeneral
Thread StartThread = null;
public void btnOptions_Click(object sender, EventArgs e)
{
StartThread = new Thread(SwitchForm);
StartThread.Start();
//Hide();
OptionGeneral option = new OptionGeneral();
option.Show();
}
public void SwitchForm()
{
StartThread.Abort();
}
Is this a new application or one you are trying to redesign that already runs forms in separate threads...
In general programming in Windows either C++, WinForms or WPF you do the following.
Make the interactions you do in the GUI event based. All forms dialogs and GUI elements live in the main thread so data passing is extremely simple and fast.
When real work needs to be done cast the work into a threadpool or task library and when the work is complete marshal the data back to the main ui thred to execute display logic.
In WPF the Dispatcher is your key to pushing data back to the UI.
It has been a LONG while since I did webforms.
If your application does not obey these rules you will suffer complicated penatlies.
If it is brand new then reboot your development with the strategies I had in mind.
If your application was designed against these rules and you are maintaining it then analyze what kind of work effort it would take to port all the features to a stable architecture and discuss with the people in charge.
When you are in the form1() form1 is the main window of the system, which is the boot window, you cannot close it and go to form2(), but you can make the main window form2() and you call form1() before the Initialize Component form2()
in Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form2());
}
in form2()
public Form2()
{
new Form1().ShowDialog();
InitializeComponent();
}
now in form1() you can close window
public Form1()
{
InitializeComponent();
}
private void btn_Close_Click(object sender, EventArgs e)
{
this.Close();
}
Do not work with UI elements directly from other thread otherwise you'll get application freeze. Use some dispatching to do it like discussed in this topic How do I update the GUI from another thread?
Another bad thing - don't use thread.Abort() call otherwise your application will be unpredictable and buggy see https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=netframework-4.8
The Thread.Abort method should be used with caution. Particularly when you call it to abort a thread other than the current thread, you do not know what code has executed or failed to execute when the ThreadAbortException is thrown. You also cannot be certain of the state of your application or any application and user state that it's responsible for preserving. For example, calling Thread.Abort may prevent the execution of static constructors or the release of unmanaged resources.
To me it seems a case of just hiding and showing the forms as per the comments, and closing Form1 if the other forms close.. Forget the showing/hiding via threading bit; there lies a world of pain (use TPL for long running operations/stay away from multithreading if you can):
class Form1{
public Form2 Form2 { get; set; }
Form1(){
//wire forms up to each other
var form3 = new Form3() { Form1 = this };
Form2 = new Form2() { Form1 = this, Form3 = form3 };
form3.Form2 = Form2;
}
void GoToForm2ButtonClick(...){
this.Hide();
Form2.Show();
}
}
class Form2{
public Form1 Form1 { get; set; }
public Form3 Form3 { get; set; }
//event handlers
void GoToForm1ButtonClick(...){
this.Hide();
Form1.Show();
}
void GoToForm3ButtonClick(...){
this.Hide();
Form3.Show();
}
void FormClosing(...){
Form1.Close();
}
}
//event handlers
class Form3{
public Form1 Form1 { get; set; }
public Form2 Form2 { get; set; }
void GoToForm1ButtonClick(...){
this.Hide();
Form1.Show();
}
void GoToForm2ButtonClick(...){
this.Hide();
Form2.Show();
}
void FormClosing(...){
Form1.Close();
}
}
And cue usual commentary about making class names meaningful, rather than just a type name followed by a number

making a cross-thread call to hide a form visual c#

Update: Solution arrived since and is now accepted. Due to the clarity of the pseudo codes on this question the solution took only a few seconds. Trying to figure out the solution from the other seemingly "duplicate" questions took a lot of time already. I had the solution in 20 minutes from the moment I asked this question. So it is not a duplicate, probably the clearest of them all to date.
While several similar questions have been asked on this, I was still not able to put together a working code from them. My main application is not on a form, but in a separate class that is a plugin and executed by a host application.
So while it seems a duplicate question it is not. Please read on.
I have my main class doing stuff. Then I have a form that displays information to the user. I need to hide this form when the user switches away from the application (host application loses focus).
I am using very limited APIs so the only methods I have at my disposal events triggered by the host application.
I created a timer that fires every 100ms and checks whether the user had the application in focus. And if not a command is sent to the form to hide itself.
The reason for this approach is because the host application loosing focus is just one of the many scenarios that I need to hide the form and I need to channel all these through the same exact method.
All works from within the rest of the classes (the Hide() method is called from the rest of the application no problem.
But it does not work when the timer calls the Hide() method, because the timer is on a different thread when it fires. So the call becomes a cross-thread call.
The very specific question is that I need an exact sample code how to make this call from the timer event handler to the form's Hide() method thread-safe with Invoke.
Thanks.
This is the timer:
private void Controllel_Opened(object sender, EventArgs e)
{
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(DisplayTimeEvent);
myTimer.Interval = 50;
myTimer.Start();
}
public static System.Timers.Timer myTimer = new System.Timers.Timer();
// This method checks different scenarios when the tool tip should be hidden and calls the hiding method
public static void DisplayTimeEvent(object source, System.Timers.ElapsedEventArgs e)
{
FormHandler.Hide();
}
Then the "FormHandler" class:
public static class FormHandler
{
private static Form1 frm1 = new Form1();
public delegate void Form1HideEventHandler();
public static event Form1HideEventHandler Form1Hide;
public static void Hide()
{
if (Form1Hide != null)
{
Form1Hide();
}
}
}
Then the form's code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FormHandler.Form1Hide += FormHandler_Form1Hide;
}
private void FormHandler_Form1Hide()
{
Hide();
}
}
I would like to get a solution with exact code if possible. Thanks.
private void FormHandler_Form1Hide()
{
if (InvokeRequired)
{
this.Invoke(new Action(() => { FormHandler_Form1Hide(); }));
}
else
{
Hide();
}
}
You need to use System.Windows.Forms.Timer instead. That will invoke back onto the dispatcher thread.

SynchronizationContext is null in winforms

I'm creating a library which relies on capturing the SynchronizationContext in order to post callbacks back to the UI thread.
A user was having a weird condition where the callbacks were being posted to the ThreadPool instead. After investigating a bit, I came up with the following two test cases:
1:
public partial class Form1 : Form
{
private Test test;
public Form1()
{
test = new Test();
InitializeComponent();
}
private class Test
{
public Test()
{
if (SynchronizationContext.Current == null)
throw new InvalidOperationException("It's null! :(");
}
}
}
2:
public partial class Form1 : Form
{
private Test test = new Test();
public Form1()
{
InitializeComponent();
}
private class Test
{
public Test()
{
if (SynchronizationContext.Current == null)
throw new InvalidOperationException("It's null! :(");
}
}
}
The 1st test runs fine, but the 2nd one throws an exception. Why?
In the second example new Test() runs (almost) as the very first code in the program. Probably, your Main function calls new Form1() which immediately calls new Test().
A SynchronizationContext must be set before it is present (obviously). There is nothing magic in the runtime that guesses that your app will use WinForms. Using WinForms is a dynamic runtime decision. WinForms will set its SynchronizationContext when you use WinForms (I forgot the exact trigger points).
In the first example the base constructor (new Form()) runs first which apparently installs the SynchronizationContext.
When you run code before any WinForms code runs no SynchronizationContext will/can be present.
There is nothing sane that your library can do about this. You could add an assert or manually set the WinForms sync context (there is a API for that) but that is hardly the business of a library. Libraries are not supposed to mess with global state. (Except if your library is clearly meant for WinForms-only use).

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

Should my Wait Dialog implement Singleton pattern?

i'm currently working on my personal Wait Dialog implementation, wich supports task progress update and task cancellation. ATM it is something like:
public partial class WaitDialog : Form
{
WaitDialog()
{
InitializeComponent();
}
public static WaitDialog Instance
{
get { return WaitDialogCreator.uniqueInstance; }
}
public DialogResult ShowDialog(Form owner, string message)
{
Instance.lblWaitMessage.Text = message;
return Instance.ShowDialog(owner);
}
public DialogResult ShowDialog(Form owner, BackgroundWorker worker)
{
...
}
public DialogResult ShowDialog(Form owner, string message, BackgroundWorker worker)
{
...
}
private class WaitDialogCreator
{
static WaitDialogCreator() { }
internal static readonly WaitDialog uniqueInstance = new WaitDialog();
}
}
In my ShowDialog() method I can pass a worker object parameter, so that i can set some properties/handlers that depends on its properies, such as the type of progress bar used (marquee if it reports progress changes, continuous otherwise), the possibility to cancel the task (according to WorkerSupportsCancellation prop), etc. The method looks like this:
public DialogResult ShowDialog(Form owner, BackgroundWorker worker)
{
if (worker == null)
{
throw new ArgumentNullException("worker", "A non-null worker must be provided.");
}
else
{
Instance.btnCancel.Enabled = worker.WorkerSupportsCancellation;
//This handler close the dialog
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(onWorkerWorkComplete);
if (worker.WorkerReportsProgress)
{
Instance.pbProgress.Style = ProgressBarStyle.Continuous;
//Update the progress bar
worker.ProgressChanged += new ProgressChangedEventHandler(onWorkerProgressChanged);
}
if (worker.WorkerSupportsCancellation)
{
Instance.btnCancel.Click += (sender, e) => { worker.CancelAsync(); };
}
}
return Instance.ShowDialog(owner);
}
I would access the wait dialog thru a controller on my parent form in this way:
public Controller(Form window)
{
this.window = window;
this.waitDialog = WaitDialog.Instance;
}
...
public void ShowWaitDialog(BackgroundWorker worker)
{
if (worker == null)
{
this.ShowWaitDialog();
}
else
{
window.BeginInvoke((MethodInvoker)delegate() { waitDialog.ShowDialog(window, worker); });
}
}
Maybe that's a very noobish question, but here it is: is it correct to apply (as I do) the Singleton Pattern in this case, or shoud i opt for normal instance creation, given that WaitDialog class ends will normally handle more than a BackGroundWorker in its lifecycle?
The thing that makes me wonder is that I can (and i will) modify WaitDialog's single instance properties each time I pass a new BackGroundWorker in my call to ShowDialog(Form, BackGroundWorker).
Is it a correct behavior, according to the pattern? Are there other path i can take for a better implementation? I am open to any suggestion.
I would creating a new instance every time.
The reason I would not use a singleton is because the form does not have any meaning beyond the use of one specific wait operation. Singleton patterns are used when you want to setup an instance of a class only once and re-use that instance over and over, with its specific settings.
No, it's a bad idea. The Form class was very much designed as a single-use class. Once a form object is disposed it is dead and cannot be revived. You'll get an ObjectDisposedException when you try to display it again. To prevent this, you'll have to intercept the FormClosing event and stop the default processing. You could call Hide() and set e.Cancel = true. But now you've got the hassle of killing it when you really want to get rid of it.
But perhaps more convincingly, you should only ever cache objects that are very expensive to create but don't take a lot of resources. The Form class is the exact opposite. Creating it is cheap but it takes a very large amount of both managed and unmanaged resources. Especially the latter, a window is a very costly OS object. It may look like a Form is expensive to create but what you see is the cycles that are burned on painting the form. You'll burn the exact same number of cycles when you show a hidden form.

Categories