【发布时间】:2020-12-15 18:29:31
【问题描述】:
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.");
}
由于某种原因,当从给定示例中的数据库加载列表时,StartProcess 方法将在调用Process.Start("calc.exe"); 之后挂起。所以计算器会出现,但随后执行停止。如果我注释掉数据库加载行,一切正常。
有什么想法吗?
谢谢。
更新: 显然我关于如何复制的说明不够清楚。我希望这会有所帮助:
- 运行以下脚本或手动执行,这将在 SQL Server 中创建一个名为 PlainTestDB 的数据库,添加一个名为 SimpleTestTable 的表,该表有两列。第一个 ID 带有 bigint 和 primarykey 标识,第二个 Name nvarchar(50),添加 3 个值 A、B 和 C。
重要提示:如果您运行脚本,请确保 CREATE DATABASE 语句之后的 go 语句位于下一行。
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')
-
在您的 Visual Studio 中创建一个新的 Windows 窗体应用程序。并添加一个带有点击处理程序的 Button。
-
向您的项目添加一个名为 PlainTestDB 的 ADO.NET 实体数据模型。
-
从数据库中选择 EF 设计器。
-
将连接字符串添加到您新创建的数据库并选中复选框以将其保存到您的应用配置中。
-
选择实体框架 6.x
-
选中表格复选框并单击完成
-
将上面的代码复制并粘贴到您的 Form1.cs 中。确保使用粘贴的代码覆盖 button1_Click 方法。
-
添加以下 using 语句
-
使用 System.Threading;
-
使用 System.Diagnostics;
-
在线上放置一个断点
Console.WriteLine("如果在调用方法中加载了实体,我永远不会被执行。");
-
在调试模式下运行程序并点击按钮
-
你会注意到计算器打开了,但是断点永远不会被命中
-
尝试一次注释掉一行,你会看到
-
注释掉数据库调用将解决挂起线程的问题
【问题讨论】:
-
您是否尝试在调试器中单步执行?尝试创建一个minimal reproducible example。我相信你会在完成之前找到解决方案。
-
移除无限循环
while (true) { },让UI线程从点击处理程序返回。 -
@DavidBrowne-Microsoft 当然可以,但是我需要同时检查 Process.Start 何时完成,它在外部进程中运行。它并没有回答这个问题,为什么 Process.Start 和 Entity Framework 会互相阻塞。
-
@AndrewSavinykh 是的,我做到了。并且调试器只是没有转到 Process.Start 下面的行。注释掉实体框架代码行时除外。 “最小的可重现示例”是上面的示例。您所要做的就是对此进行测试:将实体框架查询添加到项目中,您将能够重现该问题,正如帖子中提到的那样。显然我不能将整个 SQL Server 和实体框架代码添加到“最小可重现示例”中,因为您需要有一个特定的表和数据库。
-
可以粘贴到 VS、添加 EF 引用、指向 SQL 服务器并运行的东西。类似于this answer 中的代码块,它位于“这是一个独立的工作示例”之后。最少的代码应该创建它需要的数据库和表,就像在那个例子中一样。那将是一个“最小的可重现示例”。你的不是。
标签: c# entity-framework asynchronous