Task.Factory.StartNew аргумент "action" и локальные переменные более высокого уровня - PullRequest
2 голосов
/ 03 декабря 2010

Учтите это:

void StartUpdate(DataRequest dataRequest)
{
    Task.Factory.StartNew(request => {... do something with "request" ...}, 
        dataRequest);
}

Теперь мой вопрос: могу ли я использовать dataRequest внутри лямбда-выражения вместо передачи его в качестве второго параметра методу StartNew? Меня беспокоит то, что этот метод будет выполняться в другом потоке, и я не уверен, сохранит ли dataRequest свое состояние при использовании там.

Ответы [ 3 ]

5 голосов
/ 03 декабря 2010

Да, вы можете.
Это называется Закрытие ; это очень мощная функция.

Потокобезопасность или ее отсутствие ничем не отличаются.
Получаете ли вы экземпляр через замыкание или через параметр StartNew, это все тот же объект. (Если это не struct, что было бы неописуемо злым)

2 голосов
/ 22 марта 2011

У меня была такая же проблема. Используйте Действие вместо лямбда-выражения.

private void StartUpdate(DataRequest dataRequest)
{
    Action<DataRequest> pobjAction = new Action<DataRequest>(DoSomething);
    Task.Factory.StartNew(pobjAccion, dataRequest);
}


private void DoSomething(DataRequest dataRequest)
{
    Trace.WriteLine(dataRequest.ToString());
}
1 голос
/ 03 декабря 2010

Ответьте на свой вопрос. Вы можете, но он может не быть безопасным. Я учусь использовать ThreadLocal , чтобы помочь.

внутри вашего метода делегата должен изолировать ваш dataRequest.

ThreadLocal<DataRequest> tls = new ThreadLocal<DataRequest>();

Task.Factory.StartNew(request => {
   tls.Value = (DataRequest)stateObject;

   ///
}, dataRequest);

/ * Я получаю его от Параллельное программирование в Pro .NET на C # * /

...