【问题标题】:Dispatcher: abort dispatcher operation调度程序:中止调度程序操作
【发布时间】:2012-05-07 05:59:03
【问题描述】:

我想在线程中向 DataGrid 添加项目。

我的用户控件有视图模型:

public class Contact
{
    public string Name { get; set; }
    public string Phone { get; set; }
}

public class ContactGridViewModel
{
    public ContactGridViewModel()
    {
        Items = new ObservableCollection<Contact>();
    }

    public ObservableCollection<Contact> Items { get; private set; }

    public Dispatcher Dispatcher
    {
        get { return Dispatcher.CurrentDispatcher); }
    }
    private DispatcherOperation LastOperation { get; set; }

    public void Update(IEnumerable<Contact> contacts)
    {
        if (LastOperation != null) LastOperation.Abort();

        Items.Clear();
        foreach (var item in contacts)
            LastOperation = Dispatcher.BeginInvoke(
                    DispatcherPriority.Background,
                    new ParameterizedThreadStart(o => Items.Add(o))),
                    item);
    }
}

有标记示例:

<!--DataContext="{Binding ContactGridViewModel}-->

<DataGrid ItemsSource="{Binding Items, Mode=OneWay}">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" />
    <DataGridTextColumn Header="Phone" Binding="{Binding Path=Phone}" />
  </DataGrid.Columns>
</DataGrid>

Update 方法第二次执行后,如果第一个集合没有完全添加,DataGrid 将包含第一个集合的一部分和完整的第二个集合。

// contactList1 and contactList2 are IEnumerable<Contact> objects
Model.Update(contactList1);
Model.Update(contactList2);

我尝试中止 DispatcherOperation,但它并没有停止将联系人添加到 Items 属性中。

您能告诉我向 DataGrid ItemsSource 添加对象的正确方法吗?

【问题讨论】:

  • Abort() 返回什么?第一个收藏的哪一部分保留下来,第一个还是最后一个?
  • @LPL 它返回真。保留了第一个集合的最后一部分。

标签: wpf multithreading datagrid observablecollection dispatcher


【解决方案1】:

在您的Update(contactList1) 方法中,您为contactList1 中的每个项目启动Dispatcher.BeginInvoke(),但如果您输入Update(contactList2),您只会中止一次LastOperation,这不是完整的foreach,而是单个Items.Add()

尝试这样的事情(未测试):

public void Update(IEnumerable<Contact> contacts)
{
    if (LastOperation != null) LastOperation.Abort();

    Items.Clear();
    LastOperation = Dispatcher.BeginInvoke(
        DispatcherPriority.Background,
        new ParameterizedThreadStart(o => { foreach (var item in o) Items.Add(item); }),
        contacts);
}

【讨论】:

  • 必须等到所有项目都添加完毕
【解决方案2】:

您应该收集列表中的所有 DispatcherOpretations,然后将它们全部中止。

public class ContactGridViewModel
{
    public ContactGridViewModel()
    {
        Items = new ObservableCollection<Contact>();
        LastOperations = new List<DispatcherOperation>();
    }

    public ObservableCollection<Contact> Items { get; private set; }
    private ICollection<DispatcherOperation> LastOperations { get; set; }

    public Dispatcher Dispatcher
    {
        get { return Dispatcher.CurrentDispatcher); }
    }

    private void StopUpdating()
    {
        foreach (var operation in LastOperations)
        {
            operation.Abort();
        }
        LastOperations.Clear();
    }

    public void Update(IEnumerable<Contact> contacts)
    {
        StopUpdating();

        Items.Clear();
        foreach (var item in contacts)
            LastOperations.Add(Dispatcher.BeginInvoke(
                    DispatcherPriority.Background,
                    new ParameterizedThreadStart(o => Items.Add(item))),
                    item));
    }
}

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多