- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
以下代码运行没有问题:
// This code outputs:
// 3
// 2
// 1
//
// foo
// DotNetFiddle: https://dotnetfiddle.net/wDRD9L
public class Program
{
public static void Main()
{
Console.WriteLine("foo");
}
static Program()
{
var sb = new System.Text.StringBuilder();
var list = new List<int>() { 1,2,3 };
list.AsParallel().WithDegreeOfParallelism(4).ForAll(item => { sb.AppendLine(item.ToString()); });
Console.WriteLine(sb.ToString());
}
}
一旦我将 sb.AppendLine
替换为对 Console.WriteLine
的调用,代码就会挂起,就像某处出现死锁一样。
// This code hangs.
// DotNetFiddle: https://dotnetfiddle.net/pbhNR2
public class Program
{
public static void Main()
{
Console.WriteLine("foo");
}
static Program()
{
var list = new List<int>() { 1,2,3 };
list.AsParallel().WithDegreeOfParallelism(4).ForAll(item => { Console.WriteLine(item.ToString()); });
}
}
起初我怀疑 Console.WriteLine
不是线程安全的,但根据文档,它是线程安全的。
这种行为的解释是什么?
最佳答案
简短版本:永远不要在构造函数中阻塞,尤其是在 static
中。构造函数。
在您的示例中,差异与您使用的匿名方法有关。在第一种情况下,您捕获了一个局部变量,它导致匿名方法被编译到它自己的类中。但在第二种情况下,没有变量捕获,所以 static
方法就够了。除了将静态方法放入 Program
之外类(class)。仍在初始化中。
因此,对匿名方法的调用被类的初始化阻塞(您不能从执行静态构造函数的线程以外的线程执行类中的方法,直到该类完成初始化),并且类的初始化被匿名方法的执行阻塞(ForAll()
方法在所有这些方法都执行之前不会返回)。
死锁。
鉴于该示例(正如预期的那样)是您实际操作的简化版本,因此很难知道什么是好的变通方法。但最重要的是,您不应该在静态构造函数中进行长时间运行的计算。如果它是一个足够慢的算法,它证明使用 ForAll()
是合理的。 , 那么它就足够慢了,以至于它实际上不应该首先成为类初始化的一部分。
在解决该问题的许多可能选项中,您可能会选择一个 Lazy<T>
类,这样可以很容易地将某些初始化推迟到实际需要时进行。
例如,假设您的并行代码不只是写出列表的元素,而是以某种方式实际处理它们。 IE。它是列表实际初始化的一部分。然后您可以将该初始化包装在由 Lazy<T>
执行的工厂方法中按需而不是在静态构造函数中:
public class Program
{
public static void Main()
{
Console.WriteLine("foo");
}
private static readonly Lazy<List<int>> _list = new Lazy<List<int>>(() => InitList());
private static List<int> InitList()
{
var list = new List<int>() { 1,2,3 };
list.AsParallel().WithDegreeOfParallelism(4).ForAll(item => { Console.WriteLine(item.ToString()); });
return list;
}
}
然后初始化代码根本不会被执行,直到一些代码需要访问列表,它可以通过_list.Value
来完成。 .
这是非常微妙的不同,我觉得它需要一个新的答案(即匿名方法的使用改变了行为),但在 Stack Overflow 上至少有两个其他非常密切相关的问题和答案:
Plinq statement gets deadlocked inside static constructor
Task.Run in Static Initializer
顺便说一句:我最近了解到,使用新的 Roslyn 编译器,他们改变了在这种情况下实现匿名方法的方式,甚至那些可能是静态方法的方法都在单独的类中创建了实例方法(如果我没记错的话)。我不知道这是否是为了减少这种错误的流行,但它肯定会改变行为(并且会消除匿名方法作为死锁的来源......当然,人们总是可以重现问题对显式声明的静态命名方法的调用)。
关于c# - 使用 Console 和 PLinq 的明显死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33789721/
假设我有一个 DataTable。 var dt = getDataTable(); 然后我做 Parallel.For (0, dt.Rows.Count, i => Foo (dt.Rows[i]
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
对不起我的英语不好。所以,这是我的问题 我正在尝试通过 PLINQ 更新 DataTable 这是我的代码 DataTable table = new DataTable(); table.Colum
据我了解: Programming to leverage multicores or multiple processors is called parallel programming. 但是如果
我想对数据流执行查询,同时以一定程度的并行性并行处理项目。通常,我会使用 PLINQ,但我的工作项不受 CPU 限制,而是 IO 限制。我想使用异步IO。 PLINQ 不支持异步工作。 使用异步工作项
据我了解: Programming to leverage multicores or multiple processors is called parallel programming. 但是如果
在MSDN据说 PLINQ 不保留顺序。我想在我的项目中演示它,但我有一个问题,那就是始终保持秩序。我有一个收藏List> table这些是我的疑问: var linqQuery = table
我对 Plinq 和 Repo 模式还很陌生。我需要您提供一些引用资料和指南,以便在 fx 4.0 中使用 dbml、PLinq 实现存储库模式 最佳答案 存储库模式为您提供了对数据存储的抽象。如果带
假设您正在查询具有一百万条记录的集合,当您只有一个 CORE 处理器时,PLINQ 的性能是否与普通的 LINQ 查询有任何不同。 我知道 PLINQ 在多核处理器上工作得很好。只是想了解它在单个核心
我正在使用带有以下代码的 PLINQ: static void Main(string[] args) { var lt = new List() {1,2,3,4,5};
我正在尝试实现 PLINQ 示例但面临以下问题我的顺序查询比并行查询执行得更快。 这里是代码示例: Stopwatch sw = new Stopwatch(); in
下面是我在 Windows 服务中定期运行的示例 PLINQ 查询: var resultList = new List>(); try { resultList = emailsToSend
我写了一个 LINQ 来找出文本文件中唯一字符的频率。我还在 select 的帮助下将我的初始结果转换为一个对象。最终结果以列表的形式出现。以下是我使用的查询。 charNodes = inputSt
PLINQ 是否保证按照原始序列被操作的顺序返回查询结果,即使结果是并行产生的?例如: new List(){"a", "b", "c", "d"}.asParallel().Select(str =
许多自定义 Enumerable 扩展可以根据其他内置操作来实现 - 例如这个简单的便捷方法: public static bool AnyOf(this TElement item, IEnumer
我正在运行一个 PLINQ 查询,如下所示: ParallelQuery winningCombos = from n in nextComboMaker.GetNextCombo()
我遇到过静态构造函数中的以下 plinq 语句陷入僵局的情况: static void Main(string[] args) { new Blah(); } class Blah {
最近我对 Linq 和 Plinq 做了一些测量。我看不出 Plinq 在哪种情况下具有真正显着的优势。 我发现了很多例子,例如: Enumerable.Range(0, 10000).AsParal
PLINQ 作为 LINQ 的扩展被添加到 .NET 4.0 Framework 中。 这是什么? 它解决了什么问题? 什么时候合适,什么时候不合适? 最佳答案 这是并行 LINQ。这是一种在多核/多
产品中(基于ASP.NET MVC开发)需要经常对药品名称及名称拼音码进行下拉匹配及结果查询。为了加快查询的速度,所以我最开始就将其加入内存中(大约有六万五千条数据)。 下面附实体类。
我是一名优秀的程序员,十分优秀!