1

In my app I am running a method that takes few seconds to run and I need to fire that multiple times with different parameters to achieve what I want. Later on I started having performance problems and decided to fire those actions in multiple threads to reduce the time spent for running it. I implemented everything as expected, but when it comes for firing that thread it just freezes. It says threads are running, but never finishes. I thought maybe my methods that I am calling in threads are locking the same object and that is causing the threads to freeze, but it seems that is not the issue.

Here is a sample code:

 public abstract class ModelBase
{
    public static void RunInMultiThread(List<Action> actions)
    {

        Action testAction = new Action(() =>
        {
            Console.WriteLine("Other test");
        });
        List<Thread> threads = new List<Thread>();
        foreach (Action action in actions)
        {
            ThreadStart dlg = () => { action(); };
            Thread thread = new Thread(dlg);
            thread.Start();
            threads.Add(thread);
        }

        bool anyAlive = true;
        while (anyAlive)
        {
            anyAlive = threads.Any(t => t.IsAlive);
        }
    }
}

/// <summary>
/// This class is autogenerated
/// </summary>
public class Model : ModelBase
{
    public void FireActions()
    {
        List<Action> actions = new List<Action>();
        for (int i = 1; i <= 100; i++)
        {
            Action action = new Action(() => { DoSomething(i); });
            actions.Add(action);
        }

        RunInMultiThread(actions);
    }

    public void DoSomething(int a)
    {
        Console.WriteLine("Test " + a);
    }
}

I am creating the new instance of the Model class and calling the FireActions method. I can see the list of threads in the RunInMultiThread() method and it says all the tasks are running. I don't see anything in the output. To make it simpler, I passed the testAction action to the ThreadStart and that worked. I am very surprised why it doesn't work if I pass the actions that came in the list?

NOTE: The Model class is actually autogenerated and located on another library and it's .NET version is 4.0. That library is built using the System.CodeDom.Compiler. ModelBase class is on another project and it's .NET version is 4.7.1.

Any ideas why it won't run my actions that is passed though the list??

Andy Jones
  • 584
  • 2
  • 14
Dilshod
  • 3,189
  • 3
  • 36
  • 67
  • 1
    Is there a reason you are using `Thread`s instead of `Task`s? – mjwills Jul 31 '18 at 11:27
  • @mjwills I used the Task at first and had the same problem. – Dilshod Jul 31 '18 at 11:30
  • Maybe a silly question, but do you have .NET 4.7.1 installed? – Hyarus Jul 31 '18 at 11:59
  • @Hyarus Yes, I have bunch other projects that is on 4.7.1. – Dilshod Jul 31 '18 at 12:03
  • 1
    why not just use `Parallel.ForEach/For` and stop all this threading and actioning and make your life easier – TheGeneral Jul 31 '18 at 12:36
  • 2
    Isn't your problem related to the infamous [Lambda capture variable problem](https://stackoverflow.com/questions/451779/how-to-tell-a-lambda-function-to-capture-a-copy-instead-of-a-reference-in-c)? Your `FireActions()` method is affected by this problem (and if you are by any chance using VS2010 or older, then `RunInMultiThread()` has the same problem too). – Ňuf Jul 31 '18 at 13:53
  • This is a better duplicate: https://stackoverflow.com/questions/271440/captured-variable-in-a-loop-in-c-sharp – Enigmativity Aug 01 '18 at 06:51
  • When I pasted your code into LINQPad it ran successfully, though produced the same message 100 times due to capturing the variable, but **it did run**. Can you please explain how you're testing this? Are the actions **actually** just writing to the console when you test it or are they doing other stuff, like operating on a winforms form (as an example)? – Lasse V. Karlsen Aug 01 '18 at 06:56
  • @LasseVågsætherKarlsen The example I put there is just a sample code. In reality It is a bigger project. And in my project for the sake of test I just put Console.WriteLine("") to see if that works or not, but is not working. Example I put there is just to explain what I am doing. – Dilshod Aug 01 '18 at 09:49
  • @Enigmativity I don't think my problem is even close to what you are saying. I don't have any output issues, I would be fine if one of my methods were getting fired 100 times, but in this case it is not doing anything. It just hangs there for forever. Says thread is running. I hope that makes sense. – Dilshod Aug 01 '18 at 09:52
  • Just to be clear, you're saying that when you leave the code as posted, with Console.WriteLine, it doesn't work? – Lasse V. Karlsen Aug 01 '18 at 10:46
  • What kind of application/project is this? Console? Winforms? ASP.NET? Service? – Lasse V. Karlsen Aug 01 '18 at 10:46
  • @LasseVågsætherKarlsen Yes, I am putting a breakpoints, it goes to a point where it calls that action and after that it freezes. It doesn't output anything. This is a WPF app. – Dilshod Aug 01 '18 at 11:20
  • It should still be able to write to the console though, even though the main message loop is being blocked. Can you please respond to my clarification above, when you test it with **just** a `Console.WriteLine` it hangs? You're absolutely sure you have **no** other code inside your delegates when it hangs during test? – Lasse V. Karlsen Aug 01 '18 at 11:22
  • However, regardless of whether it works correctly with Console.WriteLine you're most likely doing something wrong. If you're spawning task or a thread in a wpf/winforms application you shouldn't hard-wait for them to complete, you should write proper asynchronous code so that you don't block the UI. It is super-easy to get into a deadlock situation like you're now experiencing. – Lasse V. Karlsen Aug 01 '18 at 11:24
  • @LasseVågsætherKarlsen Thank you for helping me on this. What I did is I tried passing another action which is created right in theRunInMultiThread method which also does the same exact work that the action that is passed and it works there. I am absolutely sure that the action that I am passing is just has Console.WriteLine("some text"). NOTE: It hangs when entering to that action, not when tries to output. – Dilshod Aug 01 '18 at 11:44

0 Answers0