Joo*_*ooj 4 .net c# lambda .net-3.5
我正在尝试这样做,但它不起作用.一些建议?
int test_i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(test_i);
test_i <- still is 0 and not 3!!!
public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(int i)
{
DisableUi();
m_commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
ConnectToServer();
i = 3; <--------------------------
// This is the continuation that will be run
// on the UI thread
return () =>
{
EnableUi();
};
});
}
Run Code Online (Sandbox Code Playgroud)
为什么我不能将test_i设置为3?我也试过ref和out,但它不起作用.
我该怎么办才能修复它?
编辑
我试过这个,但是这个方法dataSet的ouside仍然是空的.
public static void Select(DataGridView dataGridView, ref DataSet dataSet, params object[] parameters)
{
var _dataSet = dataSet;
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
_dataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
dataSet = _dataSet;
}
Run Code Online (Sandbox Code Playgroud)
i
lambda表达式中的变量指i
的是方法的参数.作为一种解决方法,您可以使其引用全局变量(脏解决方案).
顺便说一下,你不能在lambdas中捕获ref
和out
变量,但你可以将它们作为参数.您需要更改委托的签名和接收委托的方法的实现,这可能不合适:
(out int i) => { i = 10; }
Run Code Online (Sandbox Code Playgroud)
使用ref
关键字传递变量时,不能在lambda表达式中使用它.尝试在lambda中使用局部变量并在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
}
Run Code Online (Sandbox Code Playgroud)
更新
响应更新的答案:您的问题是_dataSet
lambda表达式内部与lambda表达式之外的dataSet不是同一个变量.你能做的是以下几点:
class DataSetContainer
{
public DataSet DataSet { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我们有一个带有属性的引用类型,我们可以在lambda表达式中安全地修改它:
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;
};
});
}
Run Code Online (Sandbox Code Playgroud)
}
在上面的代码中,lambda表达式将更新传递给方法DataSet
的DataSetContainer
实例的属性Select
.由于您不是修改传递的参数本身,而只是修改该实例的成员,因此不需要ref
关键字,我们也解决了关闭问题.
更新2
现在,当我打开我的大脑时,我意识到该Select
方法会进行异步调用.很可能因为代码看起来最后一行是Select
方法将在_dataSet
被分配之前很久执行,因此它将是null
.为了解决这个问题,您可能希望使用某种信令机制(例如ManualResetEvent
或AutoResetEvent
)来了解分配何时完成.