如何围绕C#4.0任务所执行的数据创建闭包?

时间:2011-08-23 23:08:30

标签: c# task-parallel-library

我正在以块的形式加密数据。我将每个数据块传递给一个像yay这样的任务:

private static Task<string> EncryptChunk( byte[] buffer, CryptoEngine c )
{
    var tcs = new TaskCompletionSource<string>();
    Task.Factory.StartNew( () =>
    {
        tcs.SetResult( c.Encrypt( buffer ) );
    } );
    return tcs.Task;
}

当我在调用此方法的代码中调试时,我可以看到它正在传递正确的块作为缓冲区参数。但是,如果我在上面的StartNew中设置断点,我看到缓冲区始终是主线程遇到的最后一个缓冲区。

我做错了什么?

1 个答案:

答案 0 :(得分:5)

我的猜测是你重复使用相同的字节数组。将捕获参数 - 但在这种情况下,由于方法中没有任何内容捕获参数,因此它有效地捕获了引用。如果您希望能够重用原始数组(即用新数据填充它)但仍然读取任务中的旧数据,则需要复制数据。例如

private static Task<string> EncryptChunk( byte[] buffer, CryptoEngine c )
{
    buffer = buffer.ToArray(); // Copy the data
    var tcs = new TaskCompletionSource<string>();
    Task.Factory.StartNew( () =>
    {
        tcs.SetResult( c.Encrypt( buffer ) );
    } );
    return tcs.Task;
}

顺便说一下,为什么在这里使用TaskCompletionSource,而不仅仅是:

return Task<string>.Factory.StartNew(() => c.Encrypt(buffer));

或使用类型推断:

return Task.Factory.StartNew(() => c.Encrypt(buffer));