Как создать замыкание вокруг данных, на которые воздействуют задачи C # 4.0? - PullRequest
4 голосов
/ 24 августа 2011

Я шифрую данные кусками. Я передаю каждый кусок данных в задачу, как 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 Ответ

5 голосов
/ 24 августа 2011

Я предполагаю, что вы повторно используете один и тот же байтовый массив.Параметр будет записан, но в этом случае, поскольку ничто в вашем методе не захватывает параметр, он фактически захватывает ссылку.Если вы хотите иметь возможность повторно использовать исходный массив (т. Е. Заполнить его новыми данными), но по-прежнему читать старые данные в рамках задачи, вам необходимо сделать копию этих данных.например,

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));
...