在具有MVVM模式的WPF应用程序中,我有一个DockManager,它根据客户的配置显示不同的窗格。
其中一些View / ViewModel使用DispatcherTimer来处理来自Queue的数据,经过一段时间后才通过并处理队列(选择此选项是因为数据以非常高的频率处理并直接绑定到DataItems会降低性能
进行一些测试我发现(并且这是正确的)即使未显示View / ViewModel也会调用DispacterTimer,这会占用主线程上的资源,这样可以更好地执行其他工作,然后更新无用的ViewModel(因为数据经常更新,因此当用户将窗格推到顶部时,99%的更新数据都是旧的
我想知道处理这些数据的最佳方法是什么。首先,我想跳过更新并将其委托给以后的进程(当视图被推到顶部时,但这样我在显示最新数据之前还有很多工作要做。
这是调度员的嘀嗒事件
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if (ScrollViewer != null)
{
HorizontalScrollViewOffset = ScrollViewer.HorizontalOffset;
VerticalScrollViewOffset = ScrollViewer.VerticalOffset;
}
lock (_queueLock)
{
while (queue.Count > 0)
{
var deal = queue.Dequeue();
Serilog.Log.Verbose($"Deal base - Dequeued {deal.Deal.Id} from deal queue");
if (deal.Status == DealStatus.New && !dealmapping.ContainsKey(deal.Deal.Id))
{
lock (DealLock)
{
Deals.Add(deal.Deal);
dealmapping = Deals.ToDictionary(x => x.Id, y => y);
}
Serilog.Log.Verbose($"Deal base - Added {deal.Deal.Id} to deals");
}
else
{
lock (DealLock)
{
if (dealmapping.ContainsKey(deal.Deal.Id))
{
var oldItem = dealmapping[deal.Deal.Id];
var index = Deals.FindIndex(x => x.Id == deal.Deal.Id);
//var index = Deals.IndexOf(oldItem);
if (index > -1)
{
if (deal.Status == DealStatus.Updated)
{
//Deals[index] = deal.Deal;
Deals[index].PopulateWith(deal.Deal);
Deals[index].IsChanged = true;
Serilog.Log.Verbose($"Deal base - Updated {deal.Deal.Id} inside deals");
}
else
{
Deals.Remove(Deals.First(x => x.Id == deal.Deal.Id));
}
}
lock (DealLock)
{
dealmapping = Deals.ToDictionary(x => x.Id, y => y);
}
}
}
}
Serilog.Log.Verbose($"Deal base - Updated lookup table with deal {deal.Deal.Id}");
}
}
}
我的第一个想法是添加if(!IsActive) return
,但这不会处理队列,有什么建议吗?
答案 0 :(得分:0)
我认为你可能是最好的" Processing"他们进来的时候。 部分原因是这个过程变得更加复杂,但无论如何都会将声音解耦为一个好的计划。
我认为得到数据的事情会更正确地#34;被认为是模型而不是视图模型。 我会在后台线程上运行它,将数据抓取到列表中。如果有很多话,可能是一份循环清单。在索引0处插入新条目,并删除索引为100或1000或其他任何内容的任何条目。 然后每10或20消息它获得新数据。 我可能使用mvvmlight messenger,但如果你的项目有prism,你可以使用eventaggregator。甚至只是一个静态桥接类作为中介。 从视图绑定附加属性以告知视图模型视图是否可见。 视图模型得到了#34;我得到了新闻"信息。 如果它的视图是可见的,那么它将从模型中重新读取数据。 如果它从isvisible false变为true,则重新从模型中读取数据。 如果需要显示大量列的大量记录,则需要保持较小的集合大小或保留多少数据。 请记住,未呈现的记录可以虚拟化,呈现数据集合的主要成本在视图中。
如果您确实需要担心该列表的大小,则可能需要采用更复杂的方法。 将新条目添加到队列(以及)。 实例化视图模型时,它会从模型中获取所有数据,如上所述。 否则,它会收到有新条目的消息。 它从fifo队列中读取新的,并将每个作为项目0插入到视图边界的observablecollection中。 该模型可以暴露该队列,或者,它可以在一个静态桥接对象中。
顺便说一下。 凭借高数据吞吐量,每次记录都可能是一个巨大的开销。答案 1 :(得分:0)
这就是y管理的方式......您必须选择处理数据的位置并在ViewModel中对其进行转换。唯一的办法就是在调度程序线程上填充observable ....
public ViewModel()
{
try
{
Messenger.Default.Register<NotificationViewModelRefresh>(this, HandleRefreshAction);
}
catch (Exception error)
{
BusinessLogger.Manage(error);
}
}
private void HandleRefreshAction(NotificationViewModelRefresh msg)
{
if (!this.IsVisible)
return;
public View()
{
InitializeComponent();
if (!DesignerProperties.GetIsInDesignMode(this))
{
this.IsVisibleChanged += (o, e) =>
{
if (this.IsVisible)
(this.DataContext as ViewModel).Refresh();
};
}
}
Task tk = Task.Factory.StartNew(() =>
{
if (System.Threading.Monitor.TryEnter(_RefreshLocker))
{
try
{
VisualHelper.InvokeBackground(() =>
{
private static void BeginInvoke(DispatcherPriority prio, Action action)
{
try
{
if (Application.Current != null)
{
if (Application.Current.Dispatcher.CheckAccess())
action();
else
Application.Current.Dispatcher.BeginInvoke(prio, (ThreadStart)(() => action()));
}
}
catch (Exception err)
{
BusinessLogger.Manage(err);
}
}
import React, { Component } from 'react';
import { Container, Header, Content, Button, Left, Icon, Body, Title, Right } from 'native-base';
import { View, StyleSheet, TextInput, ScrollView, ListView, Text } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {text: '', dataSource: ds.cloneWithRows(['hi', 'My Name is adam']),};
}
render() {
return (
<Container style={styles.container}>
<ListView
dataSource={this.state.dataSource}
style={styles.list}
renderRow={(rowData) =>
<Text style={styles.senderMessageText}>
{rowData}
</Text>
}
/>
</Container>
);
}
}
const styles = StyleSheet.create({
container:{
backgroundColor: 'green'
},
list:{
backgroundColor:'blue'
},
senderMessageText: {
backgroundColor:'red',
padding: 8,
marginTop: 10
}
});