При передаче переменной с использованием ключевого слова ref
ее нельзя использовать внутри лямбда-выражения. Попробуйте использовать локальную переменную внутри лямбды и присвойте переменную ref
вне нее, если это возможно (несколько упрощенный пример):
private static void Main(string[] args)
{
int i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref i);
Console.WriteLine(i);
}
public static void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref int i)
{
int temp = i;
Thread t = new Thread(() =>
{
temp = 3; // assign the captured, local variable
});
t.Start();
t.Join();
i = temp; // assign the ref parameter
}
Обновление
В ответ на обновленный ответ: ваша проблема в том, что _dataSet
внутри лямбда-выражения не является той же переменной, что и dataSet вне лямбда-выражения. Что вы можете сделать, это следующее:
class DataSetContainer
{
public DataSet DataSet { get; set; }
}
Теперь у нас есть ссылочный тип со свойством, которое мы можем безопасно изменить внутри лямбда-выражения:
public static void Select(DataGridView dataGridView,
DataSetContainer dataSetContainer,
params object[] parameters)
{
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
dataSetContainer.DataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
}
}
В приведенном выше коде лямбда-выражение обновит свойство DataSet
экземпляра DataSetContainer
, передаваемого методу Select
. Поскольку вы не изменяете сам передаваемый аргумент, а только член этого экземпляра, ключевое слово ref
не нужно, и мы также обходим проблему закрытия.
Обновление 2
И теперь, когда я включил свой мозг, я понял, что метод Select
делает асинхронный вызов. Вполне вероятно, что код выглядит так, что последняя строка - это метод Select
, который будет выполнен задолго до присвоения _dataSet
, и в результате это будет null
. Чтобы обойти это, вы, вероятно, захотите использовать какой-нибудь механизм сигнализации (например, ManualResetEvent
или AutoResetEvent
), чтобы знать, когда назначение выполнено.