我有一个带有一些静态属性的静态类。我在静态构造函数中初始化了所有这些属性,但后来意识到这是浪费,我应该在需要时延迟加载每个属性。因此,我转而使用 System.Lazy 类型来完成所有脏工作,并告诉它不要使用任何线程安全功能,因为在我的情况下执行始终是单线程的。
我最终得到了以下课程:
public static class Queues
{
private static readonly Lazy<Queue> g_Parser = new Lazy<Queue>(() => new Queue(Config.ParserQueueName), false);
private static readonly Lazy<Queue> g_Distributor = new Lazy<Queue>(() => new Queue(Config.DistributorQueueName), false);
private static readonly Lazy<Queue> g_ConsumerAdapter = new Lazy<Queue>(() => new Queue(Config.ConsumerAdaptorQueueName), false);
public static Queue Parser { get { return g_Parser.Value; } }
public static Queue Distributor { get { return g_Distributor.Value; } }
public static Queue ConsumerAdapter { get { return g_ConsumerAdapter.Value; } }
}
调试时,我注意到一条我从未见过的消息:
函数求值需要所有线程运行
在使用 Lazy
之前,直接显示数值。现在,我需要单击带有线程图标的圆形按钮来评估惰性值。这种情况仅发生在我正在检索 Lazy
的 .Value
的属性上。当展开实际 Lazy
对象的调试器可视化工具节点时,Value
属性仅显示 null
,而不显示任何消息。
该消息是什么意思?为什么它会显示在我的案例中?
I have a static class with some static properties. I initialized all of them in a static constructor, but then realized that it is wasteful and I should lazy-load each property when needed. So I switched to using the System.Lazy<T>
type to do all the dirty work, and told it to not to use any of its thread safety features since in my case execution was always single threaded.
I ended up with the following class:
public static class Queues
{
private static readonly Lazy<Queue> g_Parser = new Lazy<Queue>(() => new Queue(Config.ParserQueueName), false);
private static readonly Lazy<Queue> g_Distributor = new Lazy<Queue>(() => new Queue(Config.DistributorQueueName), false);
private static readonly Lazy<Queue> g_ConsumerAdapter = new Lazy<Queue>(() => new Queue(Config.ConsumerAdaptorQueueName), false);
public static Queue Parser { get { return g_Parser.Value; } }
public static Queue Distributor { get { return g_Distributor.Value; } }
public static Queue ConsumerAdapter { get { return g_ConsumerAdapter.Value; } }
}
When debugging, I noticed a message I've never seen:
The function evaluation requires all threads to run
Before using Lazy<T>
, the values were displayed directly. Now, I need to click on the round button with the threads icon to evaluate the lazy value. This happens only on my properties that are retrieving the .Value
of Lazy<T>
. When expanding the debugger visualizer node of the actual Lazy<T>
object, the Value
property simply displays null
, without any message.
What does that message mean and why is it displayed in my case?
发布评论
评论(5)
我为此苦苦挣扎了几个小时,发现有关要求所有线程运行的原始错误消息具有误导性。我从新解决方案访问现有数据库,并在新解决方案中创建新的实体框架实体 POCO 和数据访问层以访问和映射到数据库。
我最初做错了两件事。我没有在 C# 实体
POCO
中正确定义主键,并且我正在访问的table
在DB
中具有唯一的架构(它不是dbo.tablename
而是edi.tablename
)。在我的
DbContext.cs
文件中,我执行了以下操作以将表映射到正确的架构下。一旦我纠正了这些事情,错误就消失了并且工作得很好。I struggled with this for hours and found the original error message about requiring all threads to run misleading. I was accessing an existing database from a new solution and creating new
Entity Framework
entityPOCO
s and data access layers within the new solution to access and map to theDB
.I did two things initially wrong. I didn't properly define the primary key in my C# entity
POCO
, and thetable
I was accessing had a unique schema in theDB
(it was notdbo.tablename
butedi.tablename
).In my
DbContext.cs
file, I did the following to map the table under the right schema. Once I corrected these things the error went away and it worked just fine.创建一个局部变量并将其分配给您要检查的值。
这将让您检查它,因为调试器不必担心访问该属性是否会干扰您的应用程序,因为在将其分配给局部变量时它已经访问了它。
Create a local variable and assign it the value you want to inspect.
This will let you inspect it because the debugger doesn't have to worry about whether or not accessing the property will disturb your application, because it will have already accessed it when assigning it to the local variable.
对我来说,我发现是否有
this.Configuration.LazyLoadingEnabled = false;
或= true;
并不重要,无论我的 DBContext 中是否有该行。从我对这个问题的阅读来看,它似乎发生了,因为一个线程正在发生&调试器需要获得运行它的权限/在启动它之前警告您。显然,在某些情况下,您甚至可以允许它按照 MUG4N 的答案进行: 调试期间的 Visual Studio:函数评估需要所有线程运行但我发现我可以解决这个问题。
2 个选项:
在您的
队列
上添加.ToList()
:var q = db.Queues.OrderBy(e => e.Distributor).ToList();
我通过选择“非公共”找到了解决方法会员> _内部查询>对象查询>结果视图。
For me, I found it didn't matter if I had
this.Configuration.LazyLoadingEnabled = false;
or= true;
, if I had the line in my DBContext or not. It seems to occur, from my reading up on the problem, because a thread is occurring & the debugger wants permission to run it/is warning you before it spurs it. Apparently, in some cases, you can even allow it to proceed according to MUG4N's answer here: Visual Studio during Debugging: The function evaluation requires all threads to runBut what I found was I could get around the issue.
2 options:
Add
.ToList()
on yourQueues
:var q = db.Queues.OrderBy(e => e.Distributor).ToList();
I found a workaround by selecting Non-Public Members > _internalQuery > ObjectQuery > Results View.
我找到了一个标题为“如何:刷新监视值的 MSDN 页面” 解释一下:
如果有人可以给出的话,我仍然想要一个更好的解释。这没有回答的问题包括:什么样的评估需要所有线程运行?调试器如何识别这种情况?单击线程刷新图标时到底会发生什么?
编辑:我想我在检查ILSpy (出于完全不同的原因)。
Value
属性的 getter 调用了Debugger.NotifyOfCrossThreadDependency()
。 MSDN 是这么说的:因此,基本上,为了防止您尝试计算某些表达式而 Visual Studio 只是挂起 30 秒,然后通知您“函数计算已超时”的烦人情况,代码有机会通知调试器它必须解冻其他线程才能使评估成功,否则评估将永远阻塞。
由于运行其他线程可能会中断您的调试会话,通常当您计算表达式时,所有其他线程都保持冻结状态,因此调试器不会自动继续并在让您跳入兔子洞之前发出警告。
I've found an MSDN page titled "How to: Refresh Watch Values" explaining it:
I'd still like a better explanation if anyone can give it. Questions that this doesn't answer include: What kind of evaluation requires all threads to run? How does the debugger identify such a case? What exactly happens when you click the thread refresh icon?
EDIT: I think I've stumbled across the answer when examining
Lazy<T>
under ILSpy (for a completely different reason). The getter of theValue
property has a call to aDebugger.NotifyOfCrossThreadDependency()
. MSDN has this to say:So basically, to prevent the annoying case where you try to evaluate some expression and Visual Studio just hangs for 30 seconds and then informs you that "a function evaluation has timed out", the code has a chance to inform the debugger that it must unfreeze other threads for the evaluation to succeed or otherwise the evaluation will block forever.
Since running other threads may disrupt your debugging session, as usually when you evaluate an expression all other threads are kept frozen, the debugger doesn't automatically proceeed and warns you before letting you jump down the rabbit hole.
我的猜测是调试器试图通过为您加载属性来避免影响应用程序状态。
您必须记住,延迟加载仅在您引用/访问属性时发生。
现在,一般来说,您不希望调试影响应用程序的状态,否则将无法准确表示应用程序的状态(考虑多线程应用程序和调试
)看看Heisenbug
My guess would be that the debugger is trying to avoid influencing the application state by loading the properties for you.
You have to remember, that lazy load only happens when you reference/access the properties.
Now, in general, you do not want debugging to affect the state of the application, otherwise that will not give an accurate representation of what the application state should be (Think multi threaded apllications and debugging)
Have a look at Heisenbug