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

dud*_*er4 4 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;
}
Run Code Online (Sandbox Code Playgroud)

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

我究竟做错了什么?

Jon*_*eet 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;
}
Run Code Online (Sandbox Code Playgroud)

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

return Task<string>.Factory.StartNew(() => c.Encrypt(buffer));
Run Code Online (Sandbox Code Playgroud)

或使用类型推断:

return Task.Factory.StartNew(() => c.Encrypt(buffer));
Run Code Online (Sandbox Code Playgroud)