是否有可靠的方法可以在不使用取消的情况下停止线程?

时间:2019-10-25 11:04:57

标签: c# wpf async-await

我的情况似乎与大多数人所需要的相反。我不需要阻塞线程,也看不到“合作取消”该问题的好方法。

我有一个UserControl,上面有一个网格控件。该网格的选择用于通知同一UserControl上的详细信息面板。当用户选择行时,将async提取相关记录。有时,该提取所花费的时间比用户选择其他行所花费的时间长,从而导致该新行的线程化提取。当用户在网格中逐行移动时,重复此操作。例如,他们可以使用箭头键,这样他们就可以在行与列之间快速移动。

我无法阻止线程,因为我需要获取当前所选行的数据。相反,我需要一种有效的方法来立即停止先前的尝试。否则,这些提取会堆积起来,如果相关数据足够大,我有时甚至会以OutOfMemoryExceptions结尾。

这是基本概念和示例:

用户单击网格行,然后bound属性触发一种方法,该方法可获取详细数据,其中包括对相关项的访存调用:

private ObservableCollection<DataRecord> _currentData = null;
public ObservableCollection<DataRecord> CurrentData
{
    get => _currentData;
    set => SetProperty(ref _currentData, value, () => CurrentData);
}

public DataRecord SelectedRecord
{
    get => _selectedRecord;
    set
    {
        SetProperty(ref _selectedRecord, value, () => SelectedRecord);
        FetchDataAsync();
    }
}

public async void FetchDataAsync()
{
    CurrentData?.Clear();
    var dataList = await System.Threading.Tasks.Task.Run(() => GetDataList());
    CurrentData = dataList.ToObservableCollection();
}

private List<DataRecord> GetDataList()
{
    var dataList = new List<DataRecord>();
    using (var context = new DataContext(new DbFactory().GetConnectionString()))
        dataList = context.MyDataTable.Where(x => x.ID == SelectedRecord.ID).ToList();
    return dataList;
}

GetDataList()方法中进行任何实际工作的唯一一行是从数据库中获取数据,因此没有合适的位置查找Cancel标志。

我想知道我是否将通用集合用作这些返回的记录集的最终目的地是问题的一部分吗?

1 个答案:

答案 0 :(得分:0)

没有办法“立即停止”,并且不支持立即停止或取消的操作。您的GetDataList()方法没有。一旦被调用,它将一直运行直到完成或引发异常。

此外,属性设置器不应启动异步操作:https://blog.stephencleary.com/2013/01/async-oop-3-properties.html

您可以在这里处理PropertyChanged属性的SelectedRecord事件,取消当前正在执行的任何任务,然后启动另一个任务。

任务完成后,您需要确定结果是否仍然准确,或者自任务启动以来是否进行了新选择。如果是后者,则可以丢弃结果并等待最后一个结果。

处理此问题的另一种方法是使用ReactiveUI之类的支持反应性和可组合属性的库。