当我传递参数时,为什么调度程序会以这种方式运行?

时间:2015-06-01 02:15:29

标签: c# wpf dispatcher

我在WPF中使用DataGridView。 在RowEditEnding事件中,我获取旧行(编辑结束前),然后通过调度程序调用方法获取新行(编辑后)

private void myGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
    DataRowView oldRowView = e.Row.Item as DataRowView;
    DataRow oldRow = oldRowView.Row;
    //When I put a breakpoint before the dispatcher is called, oldRow has the old row values. 
    Dispatcher.BeginInvoke(new Action(() => OnRowEdit(oldRow, e)), System.Windows.Threading.DispatcherPriority.Background);
    //I have now passed the old row to OnRowEdit
}

void OnRowEdit(DataRow oldRow, DataGridRowEditEndingEventArgs e)
{
  //Here oldRow has new row values. 
}

在调用方法之前oldRow的item数组和调用方法之后的数组不匹配。这背后的原因是什么?

2 个答案:

答案 0 :(得分:1)

如果没有a good, minimal, complete code example,就无法确定您的方案中存在什么问题。这里没有足够的背景。

但最有可能的是,你只是遇到了一个时间问题。也就是说,BeginInvoke()调用的委托是异步执行的,稍后会在某些不确定的时间执行。因为它排队等待执行,所以几乎肯定会在行更新后执行,因此在执行方法时会看到新值。

可能的解决方案包括:

  1. 使用Invoke()方法代替BeginInvoke()。这是同步执行的,确保在调用OnRowEdit()方法时未修改行对象。
  2. 如果你需要的只是行中的值,那么在调用BeginInvoke()之前将它们提取到一个临时对象(例如一个新数组)中并传递那个对象而不是行对象本身
  3. 直接致电OnRowEdit()。缺乏完整的代码示例,不清楚为什么要使用BeginInvoke();通常,用户编辑操作发生在调度程序线程中,因此可以直接访问UI对象,而无需调用Invoke()BeginInvoke()。请注意,这与#1实际上是相同的选项...使用Invoke()可能只是多余的。
  4. 如果上述选项都不适合您,请通过提供一个好的代码示例来解决问题,首先解释一下您使用BeginInvoke()的原因,以及为什么这些建议都不适用于您的情况。

答案 1 :(得分:0)

Peter Duniho说要回答你的确切问题。但是"正确"在我看来,这样做的方法是使用ViewModel。然后你会得到一份" old"并且可以验证" new"这会解决你的问题(我想?)。您可以对发生的事情有更多的全面控制,MVVM还有许多其他好处。