-1

I recently created a form application through the Windows Form Application template in Visual Studio. I think the program was automatically created with multiple threads, putting the UI on one thread and whatever else on the other thread. I didn't put any code in the application to use multithreading.

Regardless I ran into and fixed the error described here. An error was thrown because I accessed a UI object from within the code block below. The issue being that the code was being ran from a different thread than the UI's thread.

What I want to know is the program actually using multiple threads? and if so how do I prevent that from happening. If not, what is happening here?

For reference, the code where I ran into this issue was in the same class that I initialize the form with. The line where I ran into the issue was on the last line in the CheckUp function (which has been altered to allow different thread access). Note: The code is structured to be moved to a console app, so the timer method and some other stuff is less kosher

public partial class Form : System.Windows.Forms.Form
{
    public Form() {
        InitializeComponent();
        System.Timers.Timer actionTimer = new System.Timers.Timer(1000);
        actionTimer.Elapsed += actionTimerTick;
        actionTimer.AutoReset = true;
        actionTimer.Enabled = true;

    }


    private void actionTimerTick(object sender, EventArgs e) {
        CheckUp();
    }


    public void CheckUp() {
        bool onlineStatus = GetOnlineStatus();
        string status = (onlineStatus) ? "Online" : "Offline";

        statusOutputLabel.Invoke((Action)(() => statusOutputLabel.Text = status ));
    }

    private static bool GetOnlineStatus() {
        /*unrelated*/
    }
}
Community
  • 1
  • 1
Mike
  • 41
  • 7
  • Did you create threads in your code? I got a feeling you don't have multiple threads – Keith Nicholas Jul 26 '16 at 22:41
  • 1
    also, for reference, saying "For reference, the code where I ran into this issue was in the main Form class." doesn't really help as you could of written any code.....if you want to give a reference, show REAL code. – Keith Nicholas Jul 26 '16 at 22:43
  • Yea probably not that clear, I was referring to the default form class created from the template - added code to clarify – Mike Jul 26 '16 at 23:11
  • Generally you want to avoid **editing** a question in such a way as to potentially **invalidate** any pre-existing **answers**. Best post as a new question –  Jul 26 '16 at 23:25
  • 1
    Please don't edit a "thanks" into the top of your question, it isn't necessary as you've marked an answer. If you want to leave something like that then post it as a comment under the answer (when you've got enough rep to comment). – slugster Jul 26 '16 at 23:27

2 Answers2

2

What I want to know is how to do manipulate the program to run everything on a single thread so that I do not have to worry about adding the extra code to manipulate UI objects,

Easy. Just don't add any explicit create-thread code in your Windows Forms app.

I recently created a form application through the Windows Form Application template in Visual Studio. The program was automatically created with multiple threads, putting the UI on one thread and whatever else on the other thread (I think).

Applications created by the Windows Forms Application template are inherently single-threaded by default so not sure why you think you have additional threads.

If you did create additional worker threads with respect to that other post, then you should use Control.BeginInvoke rather than Control.Invoke since the later can lead to potential thread dead-lock.

Additional

GUI toolkits like WinForms are potentially always single-threaded. For a jolly-good read as to why check out this article.

KGH:

The problem of input event processing is that it tends to run in the opposite direction to most GUI activity. In general, GUI operations start at the top of a stack of library abstractions and go "down". I am operating on an abstract idea in my application that is expressed by some GUI objects, so I start off in my application and call into high-level GUI abstractions, that call into lower level GUI abstractions, that call into the ugly guts of the toolkit, and thence into the OS. In contrast, input events start of at the OS layer and are progressively dispatched "up" the abstraction layers, until they arrive in my application code. Now, since we are using abstractions, we will naturally be doing locking separately within each abstraction. And unfortunately we have the classic lock ordering nightmare: we have two different kinds of activities going on that want to acquire locks in opposite orders. So deadlock is almost inevitable. Golly, tell me more...

And that's why, like Java AWT, WinForms is also single-threaded.

See also

Community
  • 1
  • 1
  • I haven't added any multithreading code to the application. However I did get an error stating that I was trying to access one thread from another. The only reason why I used the code I linked was because that's what it took to make the application work. Are worker threads added by default? – Mike Jul 26 '16 at 23:08
  • Your edit to your question shows that you are. Also note that because of this edit you have essentially made my answer obsolete –  Jul 26 '16 at 23:24
1

You are using System.Timer. https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx

For winforms apps you are better off using the one for winforms...

https://msdn.microsoft.com/en-us/library/system.windows.forms.timer(v=vs.110).aspx

It is designed to support single threaded UIs. :-

A Timer is used to raise an event at user-defined intervals. This Windows timer is designed for a single-threaded environment where UI threads are used to perform processing. It requires that the user code have a UI message pump available and always operate from the same thread, or marshal the call onto another thread.

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
  • Was using a different timer causing the separate thread error? I am using the system timer because I'll be using this code in a non-form application, and I didn't think using a different timer would make much of a difference. – Mike Jul 26 '16 at 23:14
  • 1
    The system timer is for multi threaded applications, The timer will callback on a different thread. you can use it, but you then need to marshal things back to your UI thread. – Keith Nicholas Jul 26 '16 at 23:16
  • Thanks for the response – Mike Jul 26 '16 at 23:19
  • 1
    With the OP's recent edit your answer is the best fit :) –  Jul 26 '16 at 23:26