BeginInvoke vs在EventHandler中调用,之后没有代码

时间:2016-10-31 13:50:36

标签: c# .net wpf asynchronous dispatcher

这两个片段之间究竟有什么区别:

A:

MyDataGrid.IsKeyboardFocusWithinChanged += (sender, e) => {
    if ((bool)e.NewValue == true)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
        {
            // do something
        }));
    }
};

B:

MyDataGrid.IsKeyboardFocusWithinChanged += (sender, e) => {
    if ((bool)e.NewValue == true)
    {
        Dispatcher.Invoke(DispatcherPriority.Loaded, new Action(() =>
        {
            // do something
        }));
    }
};

我认为InvokeBeginInvoke之间的唯一区别是第一个等待任务完成而后者立即返回。由于Dispatcher调用是EventHandler中唯一发生的事情,因此我认为在这种情况下使用Invoke与使用BeginInvoke具有完全相同的效果。但是我有一个工作的例子,显然并非如此。看看你自己:

MainWindow.xaml

<Window x:Class="DataGridFocusTest.MainWindow"
        x:Name="MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataGridFocusTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <TextBox DockPanel.Dock="Top"></TextBox>
        <DataGrid x:Name="MyDataGrid" DockPanel.Dock="Top" SelectionUnit="FullRow"
                  ItemsSource="{Binding SomeNumbers, ElementName=MyWindow}"
                  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Data" Binding="{Binding Data}"
                                    IsReadOnly="True" />
                <DataGridTemplateColumn Header="CheckBox">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </DockPanel>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace DataGridFocusTest
{
    public class MyDataClass
    {
        public string Data { get; set; }
    }

    public partial class MainWindow : Window
    {
        public IList<MyDataClass> SomeNumbers
        {
            get
            {
                Random rnd = new Random();
                List<MyDataClass> list = new List<MyDataClass>();

                for (int i = 0; i < 100; i++)
                {
                    list.Add(new MyDataClass() { Data = rnd.Next(1000).ToString() });
                }

                return list;
            }
        }

        public MainWindow()
        {
            InitializeComponent();

            MyDataGrid.IsKeyboardFocusWithinChanged += (sender, e) =>
            {
                if ((bool)e.NewValue == true)
                {
                    // whenever MyDataGrid gets KeyboardFocus set focus to
                    // the selected item
                    // this has to be delayed to prevent some weird mouse interaction
                    Dispatcher.Invoke(DispatcherPriority.Loaded, new Action(() =>
                    {
                        if (MyDataGrid.IsKeyboardFocusWithin &&
                            MyDataGrid.SelectedItem != null)
                        {
                            MyDataGrid.UpdateLayout();
                            var cellcontent = MyDataGrid.Columns[1].GetCellContent(MyDataGrid.SelectedItem);
                            var cell = cellcontent?.Parent as DataGridCell;
                            if (cell != null)
                            {
                                cell.Focus();
                            }
                        }
                    }));
                }
            };
        }
    }
}

我们这里有一个DataGrid,其中的行包含CheckBox。它实现了两种特定的行为:

  1. DataGrid获得键盘焦点时,它会聚焦所选行(由于某种原因,这不是默认行为)。
  2. 即使CheckBox没有聚焦,您也可以通过单击更改DataGrid的状态。
  3. 这已经有效了。假设在帖子的顶部,我认为使用InvokeBeginInvoke并不重要。但是,如果您将代码更改为BeginInvoke,则由于某种原因,2cnd行为(一键式复选框选择)不再起作用。

    我不寻找解决方案(解决方案只是使用Invoke),而是想知道为什么InvokeBeginInvoke在这种情况下表现得如此不同。

0 个答案:

没有答案