我有一个每隔几秒运行一次的功能。
private void MyTimer_Tick(object sender, EventArgs e)
{
Task.Run(() => UpdateData());
}
private void UpdateData()
{
//i have some other functions here
updateCache(list1, cachelist);
}
private void updateCache(List<T> searchResults, List<T> cacheList)
{
var result = searchResults.Where(x => !cacheList.Any(y => x.Number == y.Number && x.FileName == y.FileName));
cacheList.AddRange(result);
}
updatecache()函数中的linq查询尝试比较两个列表并更新list1(如果在cachelist中找到一些新值)。这个linq查询正在增加CPU使用率非常高,并且只要窗口打开,此函数每隔几秒运行一次,CPU使用率非常高。我怎样才能做得更好?
答案 0 :(得分:2)
让cacheList
成为HashSet
或Dictionary
,这样您就不必再循环它了。
另一个选项是使searchResults成为一个不同的类型,并在添加一个项时给它一个事件,然后订阅该事件以在cacheList中添加该项。但这实际上取决于您的架构是否允许它。
答案 1 :(得分:1)
你可以做类似下面提供的解决方案。部分性能问题可能是无意识/不受控制的并发性。如果你想让updateCache同时运行多次,你应该引入一些代码来控制它(调节线程数等)。但你可能不想要而且不需要它。更好的解决方案可能是防止重新进入updateCache。
object _updateLock = new object();
bool _isUpdating = false;
bool IsUpdating
{
get { return _isUpdating; }
set
{
lock (_updateLock)
{
_isUpdating = value;
}
}
}
private void UpdateData()
{
if (!IsUpdating)
{
IsUpdating = true;
updateCache(list1, cachelist);
IsUpdating = false;
}
}
ConcurrentDictionary<Tuple<int, string>, T> cache = new
ConcurrentDictionary<Tuple<int, string>, T>();
public void updateCache()
{
foreach (var sr in searchResults)
{
var key = new Tuple<int, string>(sr.Number, sr.FileName);
cache[key] = sr;
}
}