1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Form Multithreading in C#

Discussion in 'C, C++, C#' started by Krippleintime, Jan 2, 2011.

  1. Krippleintime

    Krippleintime Registered Member

    Joined:
    May 12, 2010
    Messages:
    96
    Likes Received:
    13
    Location:
    Graphic Location Unknown
    Hey everyone, I am learning about multithreading in C#, and can do it with a console app, but can't seem to figure out how to do it with Form's. I am trying to do a simple load file into listbox application, and make it multithreaded. If anyone has a link to a good tutorial or source, and wouldn't mind posting it, it would be of much help.

    Thanks, and happy New Year!
     
  2. vloza

    vloza Registered Member

    Joined:
    Apr 7, 2010
    Messages:
    74
    Likes Received:
    49
    Tell me a bit more what you want and i can help you. Console and Forms app are essentially the same.
     
  3. Krippleintime

    Krippleintime Registered Member

    Joined:
    May 12, 2010
    Messages:
    96
    Likes Received:
    13
    Location:
    Graphic Location Unknown
    Well right now I basically just want to get an understanding of how to multithread in a Form style app. As a starting test to get a bit of an understanding, I was just going to try something like a multi threaded list box, if thats even possible in C#. I was going to have it so that when you load a text file into a listbox, it can load a large list (500+) without lagging.
     
  4. vloza

    vloza Registered Member

    Joined:
    Apr 7, 2010
    Messages:
    74
    Likes Received:
    49
    You could use the BackgroundWorker class. It creates a thread and fires events when it finish the work.

    If you need something more advanced just tell me and i can send you an example.
     
    • Thanks Thanks x 1
  5. gainer

    gainer Newbie

    Joined:
    Nov 19, 2009
    Messages:
    21
    Likes Received:
    2
    Occupation:
    Programmer / Web Designer
    Location:
    Dirty South
    I've only done multi-threading in c++. It shouldn't be much different spawning a new thread in a form than in a console app. It really depends on what your trying to do. Keep in mind when you spawn a new thread its like firing up a new program. You can do this in your main function the default name is Program.cs this is the file that fires up the forms. Also your talking about something simple with a listbox if you want the thread to modify the listbox your listbox will need to be a global variable so the thread can have access to the variable. You should also be able to fire up thread from anywhere in application. I've never done multithreading in C# but the concept should be the same.

    Here I'll give you some c++ code I wrote in my operating systems class. Look up the Dining Philosopher problem before you look at the code and it will give you a good understanding of how threads work.

    Code:
    //Matthew ****
    //CSC 306
    //Dining Philosophers
    
    #include <iostream>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    
    #define IN_USE = false;
    #define AVAIL = true;
    
    using namespace std;
    
    void *eatRice(void *phil);
    
    //Chopsticks
    bool cs[5];
    int leftCS;
    int rightCS;
    
    void init(){
        for(int i=0; i<5; i++){
            cs[i] = true;
        }
    }
    
    int main(){
    
        init();
    
        pthread_t phils[5];
        int tid;
        for(int i=1; i<5; i++){
            tid = pthread_create(&phils[i], NULL, eatRice, (void *)i);
        }
        eatRice(0);
        tid = pthread_join(phils[1], NULL);
    
        return 0;
    }
    
    void *eatRice(void *phil){
    
        if(phil == 0){leftCS = 4;}
        else{leftCS = (long)phil-1;}
        rightCS = (long)phil;    
    
        int ate = 4;
        while(ate != 0){
            if(cs[rightCS] == true && cs[leftCS] == true){
                cs[rightCS] = false;
                cs[leftCS] = false;
                cout << "Philosopher " << (long)phil << " started eating." << endl;    
                cout << "Philosopher " << (long)phil << " finished eating." << endl;    
                for(int i = 1; i < random()%0xffffff; i++){}
                cs[rightCS] = true;
                cs[leftCS] = true;
                ate--;
            }
            else{
                for(int i = 1; i < random()%0xffff; i++){}
            }
        }
        pthread_exit(NULL);
    }
    
    
     
    • Thanks Thanks x 1
  6. Krippleintime

    Krippleintime Registered Member

    Joined:
    May 12, 2010
    Messages:
    96
    Likes Received:
    13
    Location:
    Graphic Location Unknown
    Thanks for the help from both of you. I will look more into the backgroundworker, and also read up on the Dining Philosopher problem to get a better understanding of that code.
     
  7. puremagic

    puremagic Junior Member Premium Member

    Joined:
    Sep 26, 2010
    Messages:
    110
    Likes Received:
    24

    Thanks...
     
  8. blakamia

    blakamia Junior Member

    Joined:
    Jan 25, 2010
    Messages:
    162
    Likes Received:
    343
    Also remember when modifying controls on a Form in C#, you have to use .Invoke() method, or you will get an exception for cross thread access....
     
  9. Stalli0n

    Stalli0n Junior Member

    Joined:
    Nov 17, 2010
    Messages:
    115
    Likes Received:
    83
    Location:
    Europe
    If you wanna use more threads check out the Threadpool class, very easy to handle ;)
     
  10. smack

    smack Junior Member

    Joined:
    Feb 1, 2010
    Messages:
    182
    Likes Received:
    78
    Occupation:
    Software Engineer/Evil Genius
    Location:
    inside .NET
    +1

    this is how i would go with this. in my lazier days i would turn off the cross call exceptions until one of my friends showed me the .Invoke() methods. it's pretty slick, and now i use it all over.

    Code:
    http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
    now with adding items to a listbox, i don't know that i would use more than one extra thread outside the form, and mainly just to keep the UI responsive during loading. if you try to use more than that you're going to have to worry about first loading the data in to a collection, then keeping the proper locks on the collection while multiple threads are accessing it. which for this situation is a bit overkill.

    if you're just looking to practice some of your threading chops in .NET you certainly could go deep with the load method for the listbox, but you might want to practice somewhere a bit more relevant.
     
  11. smack

    smack Junior Member

    Joined:
    Feb 1, 2010
    Messages:
    182
    Likes Received:
    78
    Occupation:
    Software Engineer/Evil Genius
    Location:
    inside .NET
    here are some examples of using Invoke() and InvokerRequired() in a multi-threaded forms application to update some controls on the form.

    the first one is incrementing a progress bar, and then using Thread.Interlocked.Increment() to increment a counting index by as well.

    Code:
            private delegate void UpdateStatusDelegate(int inc);
            private void UpdateStatus(int inc)
            {
                UpdateStatusDelegate uptot;
                object[] parms = new object[1];
    
                if (this.InvokeRequired == true)
                {
                    parms[0] = 1;
                    uptot = new UpdateStatusDelegate(UpdateStatus);
                    this.Invoke(uptot, parms);
                }
                else
                {
                    pb1.Increment(1);
                }
            }
    
    implementation would look like this:

    Code:
    UpdateStatus(1);
    in this particular case what is passed to the method is erroneous since i always want the progress bar to increment by one.

    this second one passes a control and a boolean for whether or not the control should be enabled to the method:

    Code:
            private delegate void EnableFormControlDelegate(System.Windows.Forms.Control control, bool enable);
            private void EnableFormControl(System.Windows.Forms.Control control, bool enable)
            {
                EnableFormControlDelegate uptot;
                object[] parms = new object[2];
    
                if (this.InvokeRequired == true)
                {
                    parms[0] = control;
                    parms[1] = enable;
    
                    uptot = new EnableFormControlDelegate(EnableFormControl);
                    this.Invoke(uptot, parms);
                }
                else
                {
                    control.Enabled = enable;
                }
            }
    implementation would look like this:

    Code:
    EnableFormControl(cmdStart, true);
    both of these are using the object[] method of doing this, passing your parameters in to the array in an order corresponding to the order of your members in the method signature of the target delegate function.

    now this one is a little different (aside from the obvious fact that i wrote it in VB.NET). it does NOT use the object[] to pass the information.

    Code:
        Private Delegate Sub SetButtonEnabledDelegate(ByRef Enable As Boolean)
        Private Sub SetButtonEnabled(ByRef Enable As Boolean)
            Dim uDel As SetButtonEnabledDelegate
            If Me.InvokeRequired = True Then
                uDel = New SetButtonEnabledDelegate(AddressOf SetButtonEnabled)
                Me.Invoke(uDel, Enable)
            Else
                cmdImport.Enabled = Enable
            End If
        End Sub
    implementation as follows:

    Code:
    Call SetButtonEnabled(True)
    .NET provides a lot of great multi-threading classes in addition to what you see here. Semaphore/SemaphoreSlim and Threading.Interlocked are two that are rather cool as well. there is also the newer .SyncRoot() property implemented by certain collections for threadsafe operation as well, and as someone mentioned previously ThreadPool can be useful in certain situations as well.
     
    • Thanks Thanks x 3
  12. Monrox

    Monrox Power Member

    Joined:
    Apr 9, 2010
    Messages:
    615
    Likes Received:
    579
    You can't multithread a listbox because it is a control and it is already owned by a thread. You can create many threads with their own controls. You can of course access a control owned by a different thread but the most foolproof way requires you to lock the control during access time so that no other thread can access it.

    For example, in you learning example you can create 10 threads, each will lock the listbox, load 1000 items then unlock the listbox so that the next thread can do the same. They will not run parallel and you will not get any speed advantage (rather a slowdown because of all the locking & unlocking cycles).

    If you have 10 listboxes however, you can create 10 threads and unleash each one on a listbox. This WILL finish ~10x faster. A classic usage example is downloading websites. Your internet connections is a lot faster (more throughput) than most webserver replies so you can download hundreds of websites at the same time without having to wait for a download to complete to start a new one.

    So if you want to practice, try to download (the source code of) 10 websites and save them to 10 text files at the same time. You can use this to analyze them for being a forum or a blog and what type. Then you can make an autoposter. At the end of the day you'll end up with an app that can be fed 100 000 urls and left overnight to give you tons of backlinks.

    Or you can make a multithreaded SE scraper or whatever. Just make sure your learning project compensates for something that is actually multithreadable or in other words limited by something other than a hardware bottleneck on your side.
     
    • Thanks Thanks x 1
  13. Monrox

    Monrox Power Member

    Joined:
    Apr 9, 2010
    Messages:
    615
    Likes Received:
    579
    multithreaded posting
     
  14. blakamia

    blakamia Junior Member

    Joined:
    Jan 25, 2010
    Messages:
    162
    Likes Received:
    343
    This is an extremely stupid way to go about it. Much better to organize all your data in a central public List<string>() which all 10 threads can access. Just remember to use lock() { } statements so you don't have multiple thread modifying the list at the same time and raising an exception.

    When all threads are done you just write the List<string> to a file, or a Listbox, or whatever you want, and you are done.
     
  15. Stalli0n

    Stalli0n Junior Member

    Joined:
    Nov 17, 2010
    Messages:
    115
    Likes Received:
    83
    Location:
    Europe
    Well depends on what you are doing if you have 3 listboxes usernames, passwords, proxies for example there is no point in storing them in one list...
     
  16. andrewgail

    andrewgail Newbie

    Joined:
    May 13, 2011
    Messages:
    4
    Likes Received:
    0
    C# supports parallel execution of code through multithreading. A thread is an independent execution path, able to run accompanying with added threads. A C# applicant program starts in a individual thread created automatically by the CLR and operating system (the ?main? thread), and is made multithreaded by creating additional threads.
     
  17. SLSWebber

    SLSWebber Newbie

    Joined:
    Feb 7, 2011
    Messages:
    15
    Likes Received:
    0
    Make sure your delegates are *not* part of your main form class. Put them above the class, below the 'using' declarations.
    The 'listbox' per sae, would not be multi threaded. Your threads should all write to it which causes a problem if they try to write all at the same time.
    Use a lock to keep that from happening and for Controls, you have to use Invoke.
     
  18. haylander

    haylander Registered Member

    Joined:
    May 24, 2009
    Messages:
    54
    Likes Received:
    20
    as i know , .invoke() execute the operation in the UI thread , so it is not multithreaded way.
    consider the example of list of textbox and you dedicate a separate thread foreach textbox(to update it) , it would be faster than using the .invoke .
    but in the other hand,it will reduce code clarity and produce crossthread problems.
     
  19. smack

    smack Junior Member

    Joined:
    Feb 1, 2010
    Messages:
    182
    Likes Received:
    78
    Occupation:
    Software Engineer/Evil Genius
    Location:
    inside .NET
    yes and no. the point of invoke in this particular instance is to update controls in the UI from multiple threads as they run without generating cross call exceptions.

    what you're saying about creating a list of text boxes doesn't make any sense.
     
  20. Senotaru

    Senotaru Registered Member

    Joined:
    Jan 17, 2011
    Messages:
    67
    Likes Received:
    11
    Derpin' pretty hard there Monrox? I have no idea why you would suggest using multiple listboxes. There is several ways you can do this. With a background list, dictionary, or even a queue, that is being checked for items to add on the main thread.

    You can also use .invoke or .begininvoke like people have already suggested. You won't get exceptions running on this model.

    I'm seriously perplexed in what situation you would use 10 listboxes to cover multithreading. That seems redundant and arbitrary.