我该如何诊断,减少或预防AppDomainUnloadedException?
AppDomainUnloadedException经过涉及PLINQ的长期(> 10s)测试后,NUnit 2.5.2一直在抛出.
回到2008年7月,Stephen Toub说:
是的,CTP中的调度程序不能很好地处理线程中止,这会导致进程在关闭的域中存在实时调度程序时崩溃(因为AppDomain关闭会导致该域中具有堆栈帧的所有线程上的线程中止).我们正努力为将来的版本强化这一点.
我尝试了很多解决方法,包括:
/domain:None为NUNit参数legacyUnhandledAppDomainPolicy从中删除元素nunit-console.exe.config我无法降级NUnit以降低竞争条件的可能性,因为我需要PLINQ来使我的参数测试更快.没有问题的NUnit版本不支持参数测试.
我正在寻找使用plinq在linq中利用并行编程的优势,我不确定我完全理解它的使用除了它将更有效地利用所有cpu核心这一事实,因此对于大型查询它可能更快.我可以简单地在linq调用上调用AsParallel()来使用eplinq功能,它会更快吗?或者我应该只在有大量数据要查询或处理时才使用它?
有人可以解释一件事.据我所知,AsParallel()在自己的任务中执行.那么,如果查询返回大量数据,那么当'foreach'开始执行Console.WriteLine时,变量'd'可以为空?
var integerList = Enumerable.Range(1, 100);
var d = from x in integerList.AsParallel()
where x <= 25
select x;
foreach (var v in d)
{
Console.WriteLine(v);
}
Run Code Online (Sandbox Code Playgroud) 我正在看这段代码
var numbers = Enumerable.Range(0, 20);
var parallelResult = numbers.AsParallel().AsOrdered()
.Where(i => i % 2 == 0).AsSequential();
foreach (int i in parallelResult.Take(5))
Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)
本AsSequential()应该做排序的结果数组.实际上它在执行后被排序,但如果我删除了调用AsSequential(),它仍然被调整(自AsOrdered()).
两者有什么区别?
最近我对Linq和Plinq采取了一些措施.我无法看出Plinq在哪种情况下具有真正的显着优势.
我发现了许多例子,例如:
Enumerable.Range(0, 10000).AsParallel().ForAll(_ => Thread.Sleep(50000));
Run Code Online (Sandbox Code Playgroud)
这是完全没用的例子,因为它可以平均10000度,然后会更快10000倍,但在业务应用程序中很少循环10000次并制作"IO作业".
如果有人可以提一个例子,请发布.
Plinq仅适用于Linq to Objects和Linq to XML.不建议在webserver上运行的应用程序中使用它(它有自己的线程管理).因此,我们的机会减少到具有多个核心的桌面应用程序.
通常我会编写linq查询,这些查询在几分之一秒内按顺序运行.如果我平行化并且它真的会并行运行那么会更快,但是谁在乎呢?我认为它仍然足够快.最终用户不会看到任何差异.
我可以想象一个例子,当有人从数据库获取所有数据并在内存中运行查询时.也许这很有用,但这是一个错误的设计.
TPL是异步程序编程的好东西,但我仍然不确定Plinq是一个有用的工具.
有没有人有这方面的积极经验?
我在.NET应用程序中遇到了一种奇怪的行为,它对一组内存数据执行一些高度并行的处理.
当在多核处理器(IntelCore2 Quad Q6600 2.4GHz)上运行时,它会展示非线性缩放,因为多个线程被启动以处理数据.
当作为单核上的非多线程循环运行时,该过程能够每秒完成大约240万次计算.当作为四个线程运行时,您可以预期吞吐量的四倍 - 在每秒900万次计算的某个地方 - 但是,唉,没有.在实践中,它每秒仅完成约4.1百万......与预期的吞吐量相当短.
此外,无论我使用PLINQ,线程池还是四个显式创建的线程,都会发生这种情况.很奇怪...
使用CPU时间没有其他任何东西在机器上运行,计算中也没有任何锁或其他同步对象......它应该只是在数据中前进.我已经通过在进程运行时查看perfmon数据来确认这一点(尽可能)...并且没有报告的线程争用或垃圾收集活动.
我的理论目前:
以下是代码中应该表现出相同行为的代表性摘录:
var evaluator = new LookupBasedEvaluator();
// find all ten-vertex polygons that are a subset of the set of points
var ssg = new SubsetGenerator<PolygonData>(Points.All, 10);
const int TEST_SIZE = 10000000; // evaluate the first 10 million records
// materialize the data into memory...
var polygons = ssg.AsParallel()
.Take(TEST_SIZE)
.Cast<PolygonData>()
.ToArray();
var sw1 = Stopwatch.StartNew();
// for loop completes in about 4.02 seconds... …Run Code Online (Sandbox Code Playgroud) 如何在下面的方法中创建与do-while或类似的并行等效项Update()?
TestBuffer应用程序中的另一个线程随机写入。TestBuffer.RemoveItemAndDoSomethingWithIt();应该运行直到为TestBuffer空。目前Update()仅运行枚举时集合中的项目,这是有道理的。
internal class UnOrderedBuffer<T> where T : class
{
ConcurrentBag<T> GenericBag = new ConcurrentBag<T>();
}
internal class Tester
{
private UnOrderedBuffer<Data> TestBuffer;
public void Update()
{
Parallel.ForEach(TestBuffer, Item =>
{
TestBuffer.RemoveItemAndDoSomethingWithIt();
});
}
}
Run Code Online (Sandbox Code Playgroud) 我正在使用.AsParallel().ForAll()在ASP.NET请求的上下文中并行枚举一个集合.枚举方法依赖于System.Threading.Thread.CurrentPrincipal.
我可以依赖于用于将System.Threading.Thread.CurrentPrincipal设置为处理ASP.NET请求的线程的HttpContext.Current.User的单个线程,还是我需要自己管理?
问这个问题的另一种方法是PLINQ使用的线程是否继承了调用该操作的线程的标识?
我在代码中使用Parallel.ForEach和PLINQ越多,我得到的面孔和代码审查就越多.所以我想知道我有什么理由不在每个LINQ语句中使用极端的PLINQ吗?运行时是否能够足够聪明地开始产生如此多的线程(或者从线程池中消耗这么多线程),应用程序性能实际上会降低而不是改进?同样的问题适用于并行库.
我确实理解与线程安全和使用多线程的开销相关的含义.我也意识到并不是一切都有利于并行化.所有我想知道我是否应该停止捍卫我的方法,只是放弃这两个好东西,因为我的同行认为我最好自己做线程控制而不是依靠.NET设施?
更新:请假设硬件足以满足使用多线程的先决条件.
我已经将boost的一部分 - ibeta_inv函数 - 编译成.Net 64位程序集,并且它工作得很好,直到我开始从多个线程调用它.然后它在某种程度上会返回错误的结果.
我使用此代码(C++/CLI)编写了它:
// Boost.h
#pragma once
#include <boost/math/special_functions/beta.hpp>
using namespace boost::math;
namespace Boost {
public ref class BoostMath
{
public:
double static InverseIncompleteBeta( double a, double b, double x )
{
return ibeta_inv(a,b,x);
}
};
}
Run Code Online (Sandbox Code Playgroud)
有人曾尝试过这个吗?
我没有在.Net之外尝试过这个,所以我不知道这是不是原因,但我真的不明白为什么,因为它的单线程很好.
用法(C#):
private void calcBoost(List<Val> vals)
{
//gives WRONG results (sometimes):
vals.AsParallel().ForAll(v => v.BoostResult = BoostMath.InverseIncompleteBeta(v.A, v.B, v.X));
//gives CORRECT results:
vals.ForEach(v => v.BoostResult = BoostMath.InverseIncompleteBeta(v.A, v.B, v.X));
}
Run Code Online (Sandbox Code Playgroud)
更新:从我在下面的评论中可以看出 - 我完全不确定这是一个Boost问题.也许这是一些奇怪的PLinq到C++/CLI的bug?我被废除了,以后会回来更多的事实.