我正在尝试将数据库中存储图像的数据库迁移到指向硬盘驱动器上的文件的数据库中的记录.我试图使用此方法来查询数据Parallel.ForEach以加快进程.
但是,我注意到我得到了一个OutOfMemory例外.我知道Parallel.ForEach会查询一批枚举,以减少开销的成本,如果有一个用于间隔查询(如果您一次执行一堆查询而不是间隔它们,您的源将更有可能将下一条记录缓存在内存中)出).问题是由于我返回的记录之一是1-4Mb字节数组,缓存导致整个地址空间用完(程序必须在x86模式下运行,因为目标平台将是32位机)
是否有任何方法可以禁用缓存或使TPL更小?
这是一个显示问题的示例程序.这必须在x86模式下编译,以显示问题,如果它在你的机器上花费很长时间或者没有发生,从而增加了阵列的大小(我发现1 << 20我的机器上大约需要30秒,4 << 20几乎是瞬间的)
class Program
{
static void Main(string[] args)
{
Parallel.ForEach(CreateData(), (data) =>
{
data[0] = 1;
});
}
static IEnumerable<byte[]> CreateData()
{
while (true)
{
yield return new byte[1 << 20]; //1Mb array
}
}
}
Run Code Online (Sandbox Code Playgroud) 我喜欢TPL中Parallel.For和Parallel.ForEach扩展方法的简单性.我想知道是否有办法利用类似的东西,甚至是稍微高级的任务.
下面是SqlDataReader的典型用法,我想知道是否可能,如果是这样,如何用TPL中的东西替换下面的while循环.因为读者不能提供固定数量的迭代,所以不能使用For扩展方法,这样就可以处理我将收集的任务.我希望有人可能已经解决了这个问题,然后找出了一些与ADO.net不同的事情.
using (SqlConnection conn = new SqlConnection("myConnString"))
using (SqlCommand comm = new SqlCommand("myQuery", conn))
{
conn.Open();
SqlDataReader reader = comm.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
// Do something with Reader
}
}
}
Run Code Online (Sandbox Code Playgroud) 在TPL(任务 - 并行 - 库)中是否有内置支持用于批处理操作?
我最近玩了一个例程,使用查找表即音译在字符数组上进行字符替换:
for (int i = 0; i < chars.Length; i++)
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
}
Run Code Online (Sandbox Code Playgroud)
我可以看到这可能是平凡的并行化,所以跳进了第一次刺,我知道会因为任务太细粒度而表现更差:
Parallel.For(0, chars.Length, i =>
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
});
Run Code Online (Sandbox Code Playgroud)
然后我重新编写算法以使用批处理,这样就可以将工作分成不同细粒度的不同线程.这使得线程按预期使用,并且我得到了一些接近线性的加速.
我确信必须内置支持TPL中的批处理.什么是语法,我该如何使用它?
const int CharBatch = 100;
int charLen = chars.Length;
Parallel.For(0, ((charLen / CharBatch) + 1), i =>
{
int batchUpper = ((i + 1) * CharBatch);
for (int j = i * …Run Code Online (Sandbox Code Playgroud)