3

I´m using threads in a c# program, but the process that the threads runs, calls another function that has an infinite loop that locks the program, this is, if I click another option of the Windows Form (ex: close, etc.) it will no longer response.

This loop in necessary and, by now, can not be changed.

Is there a way that I could run this loop like "background" and still use the other options in the program, this is: that the loop does not block the process (I would not like to use threads inside of threads!).

Main Program
     |
     -------Thread(Function)
                       |
                       --------In the function ANOTHER
                               function is called with 
                               an infinite loop inside 
                               (this loop is NOT part of the 
                                Thread function directly)     

EDIT: Adding some example code:

//Here I call the threads
private void userTest_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < numberOfDevices; i++)
        {
            try
            {
            Thread t = new Thread(unused => device(i, sender, e));
            t.IsBackground = true;
            t.Start();
            }
            catch (ThreadStateException f)
            {
                MessageBox.Show("ERROR:" + f);  // Display text of exception
            }
         }
      }

The thread function:

    //This infinite loop is useless, so it could be deleted. This is not
    // the loop I´m talking about
    public void device(object i, object s, object f)
    {
        while (true)
        {
            if (!killEm)
            {
                int j = (int)i;
                EventArgs g = (EventArgs)f;
                BSSDK.BS_SetDeviceID(m_ConnectedDeviceHandle[j],
                 m_ConnectedDeviceID[j], m_ConnectedDeviceType[j]);

                UserManagement userTest = new UserManagement();


                userTest.SetDevice(m_ConnectedDeviceHandle[j],
                    m_ConnectedDeviceID[j], m_ConnectedDeviceType[j]);
                userTest.ShowDialog();

            }
            else
            {
                userTest.Dispose();
                MessageBox.Show("Why don´t u kill it!!?");
                break;
            }
        }
    }

In the userTest.ShowDialog() function is the infinite loop I´m talking about

EDIT This is part of the function that is called in userTest.ShowDialog()

private void user_Click(object sender, EventArgs e) {

//THIS IS THE LOOP I´M TALKING!
while (true) {
    Keep listening for an user put his finger in the device
    ...
    Do things with that finger template
    ...   
}

}

Thank you.

  • 6
    Please show us your code; if you're using threads correctly, this won't happen. – SLaks Nov 04 '11 at 15:06
  • You need to run the thread asynchronously. – MGZero Nov 04 '11 at 15:08
  • So let me get this straight - you're opening a new window on a new thread and running an infinite loop inside that new window? – Toomai Nov 04 '11 at 15:08
  • @Toomai : yes, that´s exactly what I´m doing –  Nov 04 '11 at 15:10
  • What is being done inside the "infinite" loop ? – user957902 Nov 04 '11 at 15:14
  • @user957902 : I constantly run a functions of a bio metric device for fingerprints, so it is possible to identify an user when he puts his finger. Must be listening (looping) all the time. –  Nov 04 '11 at 15:17
  • I don't know the exact difference from Java to C# regarding threads, but if you put a non-sleeping infinite loop in a Java-Thread run method you'll lock up that process. In Java, even a "sleep(10)" call will prevent the lock up - would that not help in this situation? – Brandon Buck Nov 04 '11 at 15:18
  • Well, the thread is not locked, what is locked in the infinite loop that I use in **another** function that I call in the process of the thread. The thread itself runs OK. –  Nov 04 '11 at 15:29
  • @Kani You don't seem to understand the precise meaning of terms like thread, process, loop, function and locking. – Andrew Barber Nov 04 '11 at 16:12
  • Barely speaking: a **thread** executes a **process**. **Threads** can use **locks** for synchronization. I´m using the term **lock** in my question not in the context of a thread, but in the loop, just for say that the program hangs. Maybe I abused the notation (I changed the title of the post form locking to hanging, if it helps). –  Nov 04 '11 at 16:29
  • 1
    @Kani wrong, wrong, wrong. processes contain threads. threads do *not* execute processes. (though the code running in a thread can spawn another process... that is most certainly *not* what is happening here...) – Andrew Barber Nov 04 '11 at 16:47

5 Answers5

2

Okay; Here's the good news: You don't need threads at all. What you basically have here is a regular Windows Forms component in the form of 'forms'. Those forms must be kept 'active', to respond to events. You don't need to create threads to do this, though.

The key is the System.Windows.Forms.Application static class, which has a function tailor-made for what you need here.

System.Windows.Forms.Application.Run();

This method lets your Form objects run on, responding to events, without letting the function it is called in continue. It 'blocks', letting the message pump respond, until Application.Exit() or some other similar methods are called.

What you want to do in your case is create all of your forms, and call Show() on each one in turn (not ShowDialog()), and then finally call Application.Run(). That gets you what you want.

In order to end your program, you need to have a call to Application.Exit() happen somewhere, in response to something. You have two options that would work quickly for you:

  • Create a separate 'control form' that is just a plain Form that, when closed, calls Application.Exit(), perhaps after cycling through all your userManagement forms and closing them, first. You could do this with an event on the control form's Form.OnClosing event, for example.
  • Add an event to each of the userManagement forms' Form.OnClosing events that checks for when the last one is closed (or perhaps if any of them is closed?) and, like above, call Application.Exit() there.

Once you call Application.Exit(), any open forms should be torn down (I recommend doing it manually, first...) and then your call in the main thread to Application.Run() will complete, allowing your program to continue... we presume, to end.


EDIT: Old answer, for posterity...

You are creating your new thread in the wrong place.

Don't create a new thread for the second window. Instead, create a new thread for the long-running task, and be sure to set it as a background thread, so it doesn't stay alive even when you close the windows.

Ideally, this loop should have a way to be cancelled gracefully, but you seem to suggest you can't touch that code...

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • Well, the reason I´m creating a thread for the second windows is because this windows represents a "device", and I must have as many threads as devices. They must be running concurrently. What you mean about creating the thread for the long-running task? In this case, what would it be? (Sorry, my experience with threads is very spare) –  Nov 04 '11 at 16:18
  • @Kani OK, I just looked over the code you posted, and I have a question or two... UserTest is a Form object which is from an SDK you are using, and that is what you need to keep running, and what you can't change? – Andrew Barber Nov 04 '11 at 16:52
  • AndrewBarber : can´t change the while loop in **user_Click** which is the functions called product of **userTest.ShowDialog()**. That function has the loop I´m talking about. The threads don´t do nothing here -the problem would be the same **without** threads-, I just was saying that that function is called by a thread. –  Nov 04 '11 at 17:03
  • @Kani Okay, I think I have things figured out. I'm going to edit my answer and I'll reply again to let you know when that's done. – Andrew Barber Nov 04 '11 at 17:24
  • @Kani Alright; I've edited my answer for what I think is happening. Let me know what you think. – Andrew Barber Nov 04 '11 at 17:37
  • Thank you, I will try to implement it and see the outcome. I wlll post the results ASAP. –  Nov 04 '11 at 19:45
0

You should avoid busy loops, why cannot you loop on some sleeping or pausing system call?

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

Besides the fact if this is a good idea or not, did you try BackgroundWorker?

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=VS.80).aspx

Remy
  • 12,555
  • 14
  • 64
  • 104
  • Well, even if I use a BackgroundWorker, the infinite loop will be locking -as far I understood the documentation- because I have no way to "segementize" that part of the code. Well, I could put it a function and try. Let me try it. –  Nov 04 '11 at 15:25
0

You can create a new thread http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx

or

Perhaps using a timer would be approperiate http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.71%29.aspx

Matthew
  • 24,703
  • 9
  • 76
  • 110
  • wow, if I use threads inside threads the logic of the program would be obscured even more. I would like to avoid that if possible. Although, if in your experience that´s the standard way to solve it, I could try it! –  Nov 04 '11 at 15:22
  • @Kani There really is no such thing as "threads inside threads". Where do you get that idea? – Andrew Barber Nov 04 '11 at 15:33
  • Sorry, what I tried to say is that, in the logic of the program, I would call a thread and in the process of this thread I would call another one. Certainly, a thread is a thread. But If I obscure the logic of the program it will be very difficult to maintain in an already complicated program about biometrics :/ –  Nov 04 '11 at 15:38
0

This has nothing to do with threads - even if you call this "infinite loop function" from the main thread, it would still hang your program.

So, whoever authored this function, he/she mush have implemented some mechanism for stopping it, otherwise it would have been quite useless. Short of forcefully killing the thread (Thread.Abort), I suggest investigating this mechanism and employing it in your thread.

BTW, what is the purpose of this function? Some kind of message processing?

--- EDIT ---

OK, so your "infinite loop" is actually Form.ShowDialog. It internally contains a message pump and a way to stop that pump programmatically would be to set Form.DialogResult. Please note that you need to marshal all the UI calls to the proper threads, as indicated by this post.

Also, try running your from through Application.Run(Form), instead of Form.ShowDialog.

Community
  • 1
  • 1
Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
  • I constantly run a functions of a bio metric device for fingerprints, so it is possible to identify an user when he puts his finger. Must be listening (looping) all the time. I did implement the infinite loop but i don´t find another way to make the device listen all the time :/ –  Nov 04 '11 at 15:27
  • @Kani The fact that you have a loop has nothing to do with the *infinity* of that loop. There are several ways to stop such a loop, from simple ones such as setting a `bool` flag that is checked by the loop itself to more sophisticated ones such as TPL Task Cancellation. In your case, you'd effectively pass a "close dialog" message to the dialog's message pump (see the edit). – Branko Dimitrijevic Nov 04 '11 at 15:51
  • the thing is that the loop should **never** stop. Even in production time, it must be running constantly 24/7. I don´t want to stop the loop, what I need is to use the loop but **without** locking the program. Maybe is not possible because of the inner nature of "infinite loops" -buggy-. (Thanks for the tip about _DialogResult_, I will use in another part of the code. Is more elegant) –  Nov 04 '11 at 16:00
  • @Kani "buggy"? If you mean your code... you seem to be trying to do this every way but the correct way. – Andrew Barber Nov 04 '11 at 16:09
  • @Kani Perhaps I didn't understand your question correctly - are you saying that `ShowDialog` blacks the main thread even when called from another thread? If so, please try the `Application.Run` and see if this changes anything. You may want to take a look at: http://stackoverflow.com/questions/1566791/run-multiple-ui-threads/1569473#1569473 – Branko Dimitrijevic Nov 04 '11 at 16:13
  • @AndrewBarber : yes, I´m aware that my code is buggy, and the infinite loop is deadly wrong. But is the only way I have by now. I´m using this devices and the SDK is limitated and without documentation. I haven´t found another solution, the guys of the devices does not gives me answer and I need to solve the programming with the biometrics –  Nov 04 '11 at 16:14
  • @Kani Is there a specific reason to call `ShowDialog` instead of just `Show` (and process everything on the main UI thread)? – Branko Dimitrijevic Nov 04 '11 at 16:21
  • @BrankoDimitrijevic : Maybe I overwrote the question. Basically I have an infinite loop -let´s forget that there are threads- that locks my program. I don´t want the program to be locked. The thread I´m using calls a function which, incidentally, has a loop, that does not lock the thread in terms of execution. It executes, **but** I´m not able to use any options of that Windows Form -the one of the thread- because of the loop. Notice that the thread **is executed** –  Nov 04 '11 at 16:22
  • @BrankoDimitrijevic : yes, there is a reason, using _ShowDialog_ `will stop the thread from ending until the window is dismissed` –  Nov 04 '11 at 16:25
  • 1
    @Kani I don't know where you got your ideas about how threading works, and I don't know how much of the trouble is the imprecise nature of your use of terms (threads don't call functions... they execute them)... but I don't see this going anywhere. – Andrew Barber Nov 04 '11 at 16:45