Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Thread and Not Responding

Thread and Not Responding

Scheduled Pinned Locked Moved C#
questionhelp
17 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B brunoconde

    Greatings !!! I have a simple (I think) problem. I need a thread that executes some part of a code and during that time i want to suspent or pause the main application thread. This way the application do not appear (Not Responding) or is the same? Do you have another solution? How can i do this? Sorry for my English !!! thanks. Bruno Conde.

    T Offline
    T Offline
    Tom Larsen
    wrote on last edited by
    #2

    Arg, please don't abuse threading like this. :-) If you want to execute something in another thread yet suspend the main thread why bother seperating the two things into two threads?? You are not gaining anything using threading like this. Just do all of the work in the single main thread.

    H 1 Reply Last reply
    0
    • B brunoconde

      Greatings !!! I have a simple (I think) problem. I need a thread that executes some part of a code and during that time i want to suspent or pause the main application thread. This way the application do not appear (Not Responding) or is the same? Do you have another solution? How can i do this? Sorry for my English !!! thanks. Bruno Conde.

      H Offline
      H Offline
      Heath Stewart
      wrote on last edited by
      #3

      There's a couple ways of doing that. You can use Thread.Join in your main application thread. You would do something like this:

      Thread t = new Thread(new ThreadStart(SomeMethod));
      t.Start();
      // ...
      t.Join()

      Now your main application thread (or in whichever thread you called Join will block until the thread terminates. Another way is through asynchronous processing and gives you added functionality, like callbacks. Many objects define asynchronous methods already (the Begin* and End* method pairs), but you execute any method (including property getters and setters, which are just methods) asynchronously like so:

      using System;
      using System.Threading;
       
      delegate void VoidCallback();
       
      class Test
      {
      static void Main()
      {
      Test t = new Test();
      VoidCallback callback = new VoidCallback(t.DoSomething);
      IAsyncResult result = callback.BeginInvoke(null, null);
       
      Thread.Sleep(1000);
      Console.WriteLine("Still in Main() on main thread");
       
      callback.EndInvoke(result);
      Console.WriteLine("Done");
      }
       
      void DoSomething()
      {
      Console.WriteLine("Waiting for 3 seconds in new thread...");
      Thread.Sleep(3000);
      }
      }

      While this is possible, however, an application should never appear hung (which is what you're doing). If you don't want the user to be able to interact with the application while still allowing the control thread (the thread on which the controls were created) to paint the controls (so the application doesn't appear hung), then simply set the wait cursor by doing Cursor.Current = Cursors.WaitCursor;. You can do this for a particular control (including the form, which extends Control) by setting Control.Cursor or for the entire application by using Cursor.Current. Be sure to restore the original cursor, however, or the user won't be able to interact (i.e., give intput) with your application. For example:

      Cursor orig = Cursor.Current;
      try
      {
      Cursor.Current = Cursors.WaitCursor;
      // Do stuff...
      }
      finall
      {
      Cursor.Current = orig;
      }

      This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [

      P 1 Reply Last reply
      0
      • B brunoconde

        Greatings !!! I have a simple (I think) problem. I need a thread that executes some part of a code and during that time i want to suspent or pause the main application thread. This way the application do not appear (Not Responding) or is the same? Do you have another solution? How can i do this? Sorry for my English !!! thanks. Bruno Conde.

        A Offline
        A Offline
        Ashar Khaliq
        wrote on last edited by
        #4

        use .Join() this way this thread (whose instance is mentioned above) would wait for all child threads to "die" first before proceeding.

        1 Reply Last reply
        0
        • T Tom Larsen

          Arg, please don't abuse threading like this. :-) If you want to execute something in another thread yet suspend the main thread why bother seperating the two things into two threads?? You are not gaining anything using threading like this. Just do all of the work in the single main thread.

          H Offline
          H Offline
          Heath Stewart
          wrote on last edited by
          #5

          In most cases I would totally agree with you. There are cases, however, when you may want to execute something in another thread and eventually have your application block until it's finished. This is quite possible with the asynchronous pattern, when you first call Begin*, do something else, then block on End*. I would add, however, that's more common to use an AsyncCallback so that you don't have to block, but you could. An example might be downloading a file via HttpWebRequest.BeginGetResponse. You could update the UI and then call HttpWebREquest.EndGetResponse to block until the HttpWebResponse is returned. I'm not disagreeing that - if the original poster needs no functionality like what I descrbied - it is an abuse of threads. There may be a purpose, however (of which we would know since the original post mentioned nothing of this sort). This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

          T 1 Reply Last reply
          0
          • B brunoconde

            Greatings !!! I have a simple (I think) problem. I need a thread that executes some part of a code and during that time i want to suspent or pause the main application thread. This way the application do not appear (Not Responding) or is the same? Do you have another solution? How can i do this? Sorry for my English !!! thanks. Bruno Conde.

            B Offline
            B Offline
            brunoconde
            wrote on last edited by
            #6

            Thanks for the tip. If after i create the thread t and then do t.Join() the application don't stay "Not Responding" but it stays stopped until the thread t stopps. I think that the application stay's in "Not Responding" because in ApplicationTick1() i refer a recursive method. This method takes a while to do it's job and in that while the application stays "Not Responding". Here is a sample of the code in ApplicationTick1: // preenche a arvore MyDelegate d = new MyDelegate(LDAPLibrary.Class1.FillTreeView); this.Invoke(d,new object[] {conn,tv.Nodes,p2,true}); :((

            H 1 Reply Last reply
            0
            • H Heath Stewart

              In most cases I would totally agree with you. There are cases, however, when you may want to execute something in another thread and eventually have your application block until it's finished. This is quite possible with the asynchronous pattern, when you first call Begin*, do something else, then block on End*. I would add, however, that's more common to use an AsyncCallback so that you don't have to block, but you could. An example might be downloading a file via HttpWebRequest.BeginGetResponse. You could update the UI and then call HttpWebREquest.EndGetResponse to block until the HttpWebResponse is returned. I'm not disagreeing that - if the original poster needs no functionality like what I descrbied - it is an abuse of threads. There may be a purpose, however (of which we would know since the original post mentioned nothing of this sort). This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

              T Offline
              T Offline
              Tom Larsen
              wrote on last edited by
              #7

              Agreed, there are cases where you really need to use multi-threaded behavior and the example is a perfect example (begin/end process pipelines are classic MT fodder). Without more information however it sounds like the described problem can be fixed simply by avoiding MT all together. Sometimes the vague nature of the questions makes me suspicious which is why I asked the question. :-) If they can come up with the answer on why their app relies on MT behavior that requires going against MT behavior then we can actually go forward and get a better solution than vaguely throwing code around.

              H 1 Reply Last reply
              0
              • B brunoconde

                Thanks for the tip. If after i create the thread t and then do t.Join() the application don't stay "Not Responding" but it stays stopped until the thread t stopps. I think that the application stay's in "Not Responding" because in ApplicationTick1() i refer a recursive method. This method takes a while to do it's job and in that while the application stays "Not Responding". Here is a sample of the code in ApplicationTick1: // preenche a arvore MyDelegate d = new MyDelegate(LDAPLibrary.Class1.FillTreeView); this.Invoke(d,new object[] {conn,tv.Nodes,p2,true}); :((

                H Offline
                H Offline
                Heath Stewart
                wrote on last edited by
                #8

                That won't start a new thread. Control.Invoke actually executes the method on the thread on which the control was created. That's useful when you're doing something in a different thread and need to update the UI. As I said in my reply, you must always update the UI on the thread on which the control was created. That's why the Control class implements ISynchronizeInvoke. This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                1 Reply Last reply
                0
                • T Tom Larsen

                  Agreed, there are cases where you really need to use multi-threaded behavior and the example is a perfect example (begin/end process pipelines are classic MT fodder). Without more information however it sounds like the described problem can be fixed simply by avoiding MT all together. Sometimes the vague nature of the questions makes me suspicious which is why I asked the question. :-) If they can come up with the answer on why their app relies on MT behavior that requires going against MT behavior then we can actually go forward and get a better solution than vaguely throwing code around.

                  H Offline
                  H Offline
                  Heath Stewart
                  wrote on last edited by
                  #9

                  And I completely agree with you. I added a response to yours mainly for the original poster's benefit, since he/she might have a valid reason that falls under the scenario I mentioned. Turns out, though, that he/she is using Control.Invoke, apparently thinking that it will invoke the method on a different thread. Further proof that reading documentation is always beneficial. :) This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                  1 Reply Last reply
                  0
                  • H Heath Stewart

                    There's a couple ways of doing that. You can use Thread.Join in your main application thread. You would do something like this:

                    Thread t = new Thread(new ThreadStart(SomeMethod));
                    t.Start();
                    // ...
                    t.Join()

                    Now your main application thread (or in whichever thread you called Join will block until the thread terminates. Another way is through asynchronous processing and gives you added functionality, like callbacks. Many objects define asynchronous methods already (the Begin* and End* method pairs), but you execute any method (including property getters and setters, which are just methods) asynchronously like so:

                    using System;
                    using System.Threading;
                     
                    delegate void VoidCallback();
                     
                    class Test
                    {
                    static void Main()
                    {
                    Test t = new Test();
                    VoidCallback callback = new VoidCallback(t.DoSomething);
                    IAsyncResult result = callback.BeginInvoke(null, null);
                     
                    Thread.Sleep(1000);
                    Console.WriteLine("Still in Main() on main thread");
                     
                    callback.EndInvoke(result);
                    Console.WriteLine("Done");
                    }
                     
                    void DoSomething()
                    {
                    Console.WriteLine("Waiting for 3 seconds in new thread...");
                    Thread.Sleep(3000);
                    }
                    }

                    While this is possible, however, an application should never appear hung (which is what you're doing). If you don't want the user to be able to interact with the application while still allowing the control thread (the thread on which the controls were created) to paint the controls (so the application doesn't appear hung), then simply set the wait cursor by doing Cursor.Current = Cursors.WaitCursor;. You can do this for a particular control (including the form, which extends Control) by setting Control.Cursor or for the entire application by using Cursor.Current. Be sure to restore the original cursor, however, or the user won't be able to interact (i.e., give intput) with your application. For example:

                    Cursor orig = Cursor.Current;
                    try
                    {
                    Cursor.Current = Cursors.WaitCursor;
                    // Do stuff...
                    }
                    finall
                    {
                    Cursor.Current = orig;
                    }

                    This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [

                    P Offline
                    P Offline
                    PaleyX
                    wrote on last edited by
                    #10

                    When I set Cursor.Current to the WaitCursor then start a thread to do a long process the Cursor doesn't remain as the WaitCursor it almost immediately changes back to the default cursor. My long process fires an event to say it has started and I handle that on the GUI thread (yes I am using invoke required and delegates) - this sets the Cursor.Current to the WaitCursor then when the long process has completed it fires another event which is handled on the GUI thread which sets the Cursor.Current to the default cursor. I would like the Cursor to remain as the WaitCursor until the long process has completed but no amount of jiggery pokery seems to enable me to do that - I have had to resort to disabling huge amounts of the GUI so the user can't mess up - a WaitCursor would be nice but it just isn't happening. I know the following is in VB but I haven't had much joy on the VB forum. The long running process fires off an event every 1000 records or so which is handled on the GU thread thus: Private Delegate Sub xxxDelegate(ByVal sender As Object, ByVal e As xxxEventArgs) Private Sub xxx(ByVal sender As Object, ByVal e As xxxEventArgs) Handles LongProcess.xxx If button.InvokeRequired = False Then Console.WriteLine("A - " & Cursor.Current.ToString()) ... Else Console.WriteLine("B - " & Cursor.Current.ToString()) Dim del As New xxxDelegate(AddressOf xxx) Me.BeginInvoke(del, New Object() {sender, e}) End If End Sub When run the following is written to the console: B - [Cursor: WaitCursor] A - [Cursor: Default] B - [Cursor: WaitCursor] A - [Cursor: Default] B - [Cursor: WaitCursor] A - [Cursor: Default]

                    H 1 Reply Last reply
                    0
                    • P PaleyX

                      When I set Cursor.Current to the WaitCursor then start a thread to do a long process the Cursor doesn't remain as the WaitCursor it almost immediately changes back to the default cursor. My long process fires an event to say it has started and I handle that on the GUI thread (yes I am using invoke required and delegates) - this sets the Cursor.Current to the WaitCursor then when the long process has completed it fires another event which is handled on the GUI thread which sets the Cursor.Current to the default cursor. I would like the Cursor to remain as the WaitCursor until the long process has completed but no amount of jiggery pokery seems to enable me to do that - I have had to resort to disabling huge amounts of the GUI so the user can't mess up - a WaitCursor would be nice but it just isn't happening. I know the following is in VB but I haven't had much joy on the VB forum. The long running process fires off an event every 1000 records or so which is handled on the GU thread thus: Private Delegate Sub xxxDelegate(ByVal sender As Object, ByVal e As xxxEventArgs) Private Sub xxx(ByVal sender As Object, ByVal e As xxxEventArgs) Handles LongProcess.xxx If button.InvokeRequired = False Then Console.WriteLine("A - " & Cursor.Current.ToString()) ... Else Console.WriteLine("B - " & Cursor.Current.ToString()) Dim del As New xxxDelegate(AddressOf xxx) Me.BeginInvoke(del, New Object() {sender, e}) End If End Sub When run the following is written to the console: B - [Cursor: WaitCursor] A - [Cursor: Default] B - [Cursor: WaitCursor] A - [Cursor: Default] B - [Cursor: WaitCursor] A - [Cursor: Default]

                      H Offline
                      H Offline
                      Heath Stewart
                      wrote on last edited by
                      #11

                      You wouldn't be calling Application.DoEvents would you? If not, you might run your application through a profiler (available from MSDN[^] even) to see if it's getting called automatically be something else. From the .NET Framework SDK for the Cursor.Current property:

                      Note If you call Application.DoEvents before resetting the Current property back to the Cursors.Default cursor, the application will resume listening for mouse events and will resume displaying the appropriate Cursor for each control in the application.

                      This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                      P 1 Reply Last reply
                      0
                      • H Heath Stewart

                        You wouldn't be calling Application.DoEvents would you? If not, you might run your application through a profiler (available from MSDN[^] even) to see if it's getting called automatically be something else. From the .NET Framework SDK for the Cursor.Current property:

                        Note If you call Application.DoEvents before resetting the Current property back to the Cursors.Default cursor, the application will resume listening for mouse events and will resume displaying the appropriate Cursor for each control in the application.

                        This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                        P Offline
                        P Offline
                        PaleyX
                        wrote on last edited by
                        #12

                        The app does call DoEvents but not anywhere touched by the long process - I usually call DoEvents after closing down a Dialog. I have run it under a profiler and DoEvents doesn't come into it. I am kicking off the long process using BeginInvoke - if that helps.

                        H 1 Reply Last reply
                        0
                        • P PaleyX

                          The app does call DoEvents but not anywhere touched by the long process - I usually call DoEvents after closing down a Dialog. I have run it under a profiler and DoEvents doesn't come into it. I am kicking off the long process using BeginInvoke - if that helps.

                          H Offline
                          H Offline
                          Heath Stewart
                          wrote on last edited by
                          #13

                          Where do you actually set Cursor.Current? Can you show me the rest of the code minus your application-specific implementation? This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                          P 1 Reply Last reply
                          0
                          • H Heath Stewart

                            Where do you actually set Cursor.Current? Can you show me the rest of the code minus your application-specific implementation? This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                            P Offline
                            P Offline
                            PaleyX
                            wrote on last edited by
                            #14

                            Hope this makes sense

                            Private Delegate Sub RunCrosstabDelegate(ByVal rowVar As String, ByVal colVar As String, ByVal thirdVar As String)
                            
                            Private Sub RunCrosstab()
                                   Dim crosstab As New RunCrosstabDelegate(AddressOf \_Counter.RunCrossTab)
                                    crosstab.BeginInvoke(LkCrossTab1.RowVariable, LkCrossTab1.ColVariable, LkCrossTab1.ThirdVariable, Nothing, Nothing)
                            End Sub
                            

                            Private Sub _Counter_CrossTabStart(ByVal sender As Object, ByVal e As EventArgs) Handles _Counter.CrossTabStart
                            If LkCrossTab1.InvokeRequired = False Then
                            Cursor.Current = System.Windows.Forms.Cursors.WaitCursor
                            Else
                            Dim del As New CrossTabStartDelegate(AddressOf _Counter_CrossTabStart)
                            Me.BeginInvoke(del, New Object() {sender, e})
                            End If
                            End Sub

                            Private Delegate Sub CrossTabFinishedDelegate(ByVal sender As Object, ByVal e As EventArgs)
                            
                            Private Sub \_Counter\_CrossTabFinished(ByVal sender As Object, ByVal e As EventArgs) Handles \_Counter.CrossTabFinished
                            
                                If LkCrossTab1.InvokeRequired = False Then
                                       Cursor.Current = System.Windows.Forms.Cursors.Default
                                       '
                                Else
                                    Dim del As New CrossTabFinishedDelegate(AddressOf \_Counter\_CrossTabFinished)
                                    Me.BeginInvoke(del, New Object() {sender, e})
                                End If
                            
                            End Sub
                            
                            H 1 Reply Last reply
                            0
                            • P PaleyX

                              Hope this makes sense

                              Private Delegate Sub RunCrosstabDelegate(ByVal rowVar As String, ByVal colVar As String, ByVal thirdVar As String)
                              
                              Private Sub RunCrosstab()
                                     Dim crosstab As New RunCrosstabDelegate(AddressOf \_Counter.RunCrossTab)
                                      crosstab.BeginInvoke(LkCrossTab1.RowVariable, LkCrossTab1.ColVariable, LkCrossTab1.ThirdVariable, Nothing, Nothing)
                              End Sub
                              

                              Private Sub _Counter_CrossTabStart(ByVal sender As Object, ByVal e As EventArgs) Handles _Counter.CrossTabStart
                              If LkCrossTab1.InvokeRequired = False Then
                              Cursor.Current = System.Windows.Forms.Cursors.WaitCursor
                              Else
                              Dim del As New CrossTabStartDelegate(AddressOf _Counter_CrossTabStart)
                              Me.BeginInvoke(del, New Object() {sender, e})
                              End If
                              End Sub

                              Private Delegate Sub CrossTabFinishedDelegate(ByVal sender As Object, ByVal e As EventArgs)
                              
                              Private Sub \_Counter\_CrossTabFinished(ByVal sender As Object, ByVal e As EventArgs) Handles \_Counter.CrossTabFinished
                              
                                  If LkCrossTab1.InvokeRequired = False Then
                                         Cursor.Current = System.Windows.Forms.Cursors.Default
                                         '
                                  Else
                                      Dim del As New CrossTabFinishedDelegate(AddressOf \_Counter\_CrossTabFinished)
                                      Me.BeginInvoke(del, New Object() {sender, e})
                                  End If
                              
                              End Sub
                              
                              H Offline
                              H Offline
                              Heath Stewart
                              wrote on last edited by
                              #15

                              In your previous post you made it sounds like there was also an event that fired intermitently while the long process was running. Is that true? If so, do you set the wait cursor at all in that loop? When you profiled your application, no Application.DoEvents ran at all while processing the crosstab? From the code above I don't see a problem. It would seem another thread is either setting the cursor or dispatching queued messages (in the application pump). Since you're running asynchronously, this is entirely possible and most likely the case. Try running this synchronously and you should find that it works because the application (or dialog) message pump is run (which Application.DoEvents forces). If that does work, I'm really not sure what to do to work around it, since this is expected behavior. One thing you could try is setting a Control's Cursor property instead of the application's. Hopefully that will "stick". This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                              P 1 Reply Last reply
                              0
                              • H Heath Stewart

                                In your previous post you made it sounds like there was also an event that fired intermitently while the long process was running. Is that true? If so, do you set the wait cursor at all in that loop? When you profiled your application, no Application.DoEvents ran at all while processing the crosstab? From the code above I don't see a problem. It would seem another thread is either setting the cursor or dispatching queued messages (in the application pump). Since you're running asynchronously, this is entirely possible and most likely the case. Try running this synchronously and you should find that it works because the application (or dialog) message pump is run (which Application.DoEvents forces). If that does work, I'm really not sure what to do to work around it, since this is expected behavior. One thing you could try is setting a Control's Cursor property instead of the application's. Hopefully that will "stick". This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                                P Offline
                                P Offline
                                PaleyX
                                wrote on last edited by
                                #16

                                DoEvents isn't called at all during the processing. The WaitCursor just won't stick - I have tried setting the cursor on every single control to the WaitCursor - which kind of works although it doesn't stop mouseinput - the user can still click on things, drag stuff around, press buttons etc. So the WaitCursor doesn't seem to do much - is that what is supposed to happen? Is there a way to disable mouseinput without disabling every single control?

                                H 1 Reply Last reply
                                0
                                • P PaleyX

                                  DoEvents isn't called at all during the processing. The WaitCursor just won't stick - I have tried setting the cursor on every single control to the WaitCursor - which kind of works although it doesn't stop mouseinput - the user can still click on things, drag stuff around, press buttons etc. So the WaitCursor doesn't seem to do much - is that what is supposed to happen? Is there a way to disable mouseinput without disabling every single control?

                                  H Offline
                                  H Offline
                                  Heath Stewart
                                  wrote on last edited by
                                  #17

                                  What are you using to profile the execution of your application? On other thing you might try is to override OnCursorChanged and set a breakpoint to see if anything else is setting it. Note that this event handler is not called if a native call changes it. You could set Form.KeyPreview on the container form and disable keys effectively, but to disable mouse events for all child controls you'll need override WndProc on the form and handle the WM_PARENTNOTIFY (0x0210) message, where the low order (second half) of the Message.LParam is set to WM_LBUTTONDOWN (0x0201) or WM_RBUTTONDOWN (0x0204), and conditionally handle the message (allow it to be processed by calling base.WndProc(ref Message)). Your code must be fully trusted to override WndProc. This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Sustained Engineering Microsoft [My Articles] [My Blog]

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups