0
private void button1_Click(object sender, EventArgs e)
{
    // Comment out the following line and the StartProcess Method works fine
    List<SimpleTestTable> list = new PlainTestDBEntities().SimpleTestTables.ToList();

    new Thread(StartProcess).Start();

    while (true)
    { }
}

private void StartProcess()
{
    Thread.Sleep(2000);

    Console.WriteLine("I am executed totally fine.");

    Process.Start("calc.exe");

    Console.WriteLine("I am never executed if Entities are loaded in the calling method.");
}

For some reason, when the list is loaded from the DB in the given example, the StartProcess Method will hang after the Call of Process.Start("calc.exe");. So the calculator will show up, but then the execution stops. If I comment out the DB loading line, everything works fine.

Any ideas?

Thank you.

Update: Apparently my instructions on how to reproduce wasn't clear enough. I hope this will help:

  1. Run the following script or do it manually which will create a DataBase in your SQL Server, with the Name PlainTestDB, add a table with the name SimpleTestTable, which has two columns. First ID with bigint and primarykey identity on, second Name nvarchar(50), add 3 values A, B and C.

Important: If you run the script make sure the go statement after the CREATE DATABASE statement is on the next line.

    use master
go

CREATE DATABASE [PlainTestDB] CONTAINMENT = NONE ON PRIMARY ( NAME = N'PlainTestDB', FILENAME = N'C:\Data\PlainTestDB.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB ) LOG ON ( NAME = N'PlainTestDB_log', FILENAME = N'C:\Data\PlainTestDB_log.ldf' , SIZE = 8192KB , MAXSIZE = 2048GB , FILEGROWTH = 65536KB ) WITH CATALOG_COLLATION = DATABASE_DEFAULT 
GO

use [PlainTestDB]

CREATE TABLE [dbo].[SimpleTestTable]( [ID] [bigint] IDENTITY(1,1) NOT NULL, [Name] nvarchar NOT NULL, CONSTRAINT [PK_SimpleTestTable] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY]

USE [PlainTestDB]

INSERT INTO [dbo].[SimpleTestTable] ([Name]) VALUES ('A'),('B'),('C')
  1. Create a new Windows Forms Application in your Visual Studio. And add a Button with a click handler.

  2. Add an ADO.NET Entity Data Model to your project with the name PlainTestDB.

  3. Choose EF Designer from Database.

  4. Add a connection string to your newly created database and check the box for saving it to your app config.

  5. Choose Entity Framework 6.x

  6. Check the Tables Checkbox and click Finish

  7. Copy and paste the code above in your Form1.cs. Make sure you override the button1_Click method with the code you paste.

  8. Add the following using statements

  9. using System.Threading;

  10. using System.Diagnostics;

  11. Place a Breaking Point on the Line

    Console.WriteLine("I am never executed if Entities are loaded in the calling method.");

  12. Run the Program in Debug mode and click on the button

  13. You will notice that the Calculator opens, but the breakpoint never gets hit

  14. Play around with commenting out one line at a time and you will see

  15. Commenting out the Database call will solve the issue with the hanging Thread

TheVillageIdiot
  • 40,053
  • 20
  • 133
  • 188
Chris
  • 305
  • 4
  • 19
  • Did you try to step through in a debugger? Try creating a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). I'm sure you will have solution before you finished. – Andrew Savinykh Aug 26 '20 at 22:20
  • Remove the infinite loop `while (true) { }` and let the UI thread return from the click handler. – David Browne - Microsoft Aug 26 '20 at 22:53
  • @DavidBrowne-Microsoft Of course that would work, but I need that while to check when the Process.Start has finished, which is running in an external Process. And it does not answer the question, why Process.Start and Entity Framework are blocking each other. – Chris Aug 27 '20 at 09:49
  • @AndrewSavinykh Yes I did. And the Debugger just does not go to the line below the Process.Start. Except when commenting out the Entity Framework code line. The "minimal reproducible example" is the example above. All you have to do to test this: Add an Entity Framework query to the project and you will be able to reproduce the issue, exactly as mentioned in the post. Obviously I can not add the whole SQL Server and the Entity Framework code to the "minimal reproducible example", since you will need to have a certain table and database. – Chris Aug 27 '20 at 09:58
  • Something that one could paste to VS, add EF reference, point to a SQL server and run. Similar to block of code in [this answer](https://stackoverflow.com/a/24543797/284111) that goes after "Here is a self-contained working example". The minimal code should create the database and table it requires like in that example. That would be a "minimal reproducible example". Yours is not. – Andrew Savinykh Aug 27 '20 at 11:32
  • @AndrewSavinykh I added some more instructions on how to reproduce the issue. I hope this helps. – Chris Aug 27 '20 at 14:27

1 Answers1

0
    private void button1_Click(object sender, EventArgs e)
    {
        new Thread(BackgroundWorker).Start();
    }

    private void BackgroundWorker()
    {
        List<SimpleTestTable> list = new PlainTestDBEntities().SimpleTestTables.ToList();

        new Thread(StartProcess).Start();

        while (true)
        { 
            // Wait for the external Process to complete its work.
        }
    }

    private void StartProcess()
    {
        Thread.Sleep(2000);

        Console.WriteLine("I am executed totally fine.");

        Process.Start("calc.exe");

        Console.WriteLine("I am now always executed because there is no UI handler interfering with Entity Framework and Process.Start");
    }

This solves the problem. After trying the first example in a Console Application I saw that it works just fine. So thanks to the hint in one of the friendly comments about the UI handler, I figured, that the UI handler must complete it's work first in order for all the threads to run properly.

But it still does not answer why the phenomena occurs in the first place. Why does Entity Framework, Click Handler and Process.Start block each other in the first example? And you can test that easily, set up a simple project with an Entity Framework table, load as mentioned in the first example. As soon as you remove either the Entity Framework code, the while() or the Process.Start it works. But not all of them together.

Would be very interesting to know, why exactly is that.

Chris
  • 305
  • 4
  • 19
  • Start.Process uses ShellExecute. ShellExecutes may delegate execution to Shell extensions that are activated using COM. Depending on apartment model of the process, COM message passing can rely on the process message pump. You are blocking message pump by `while (true)`. – Andrew Savinykh Aug 27 '20 at 12:30
  • Entities is a red herring, I don't think it has anything to do with anything. If you could provide a reproducible example, then we could look at it in more details, without it it's not possible to reproduce. – Andrew Savinykh Aug 27 '20 at 12:32