Dispatcher:中止调度程序操作

时间:2012-04-26 13:30:23

标签: wpf multithreading datagrid observablecollection dispatcher

我想在线程中向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添加对象的正确方法吗?

2 个答案:

答案 0 :(得分: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));
    }
}

答案 1 :(得分: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);
}