我试图运行的结果显示在窗口中的冗长的操作,而不会阻塞UI线程。 我已经是一个View
具有ListView
控件,它结合到ObservableCollection
在我的ViewModel
。 我也有一些其他TextBlock
结合两个阵列控制器。 该范围内的冗长的操作之前运行任何Task
获取显示和任何之后没有。 这里是我的代码,以帮助你明白我的意思:
四年:
<TextBlock TextWrapping="Wrap" Grid.Row="1"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding Years[1]}"/>
<Run Text=":"/>
</TextBlock>
<TextBlock TextWrapping="Wrap" Grid.Row="2"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding Years[2]}"/>
<Run Text=":"/>
</TextBlock>
<TextBlock TextWrapping="Wrap" Grid.Row="3"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding Years[3]}"/>
<Run Text=":"/>
</TextBlock>
四个字段每年举行的计数。
<TextBlock Text="{Binding YearCounts[0]}" TextWrapping="Wrap"
Grid.Column="1" Margin="10,0,0,0"/>
<TextBlock Text="{Binding YearCounts[1]}" TextWrapping="Wrap"
Grid.Column="1" Grid.Row="1" Margin="10,0,0,0"/>
<TextBlock Text="{Binding YearCounts[2]}" TextWrapping="Wrap"
Grid.Column="1" Grid.Row="2" Margin="10,0,0,0"/>
<TextBlock Text="{Binding YearCounts[3]}" TextWrapping="Wrap"
Grid.Column="1" Grid.Row="3" Margin="10,0,0,0"/>
ListView
,以保持每个记录的信息:
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Header="Report Number"
DisplayMemberBinding="{Binding RepNum}"/>
<GridViewColumn Header="Employee ID"
DisplayMemberBinding="{Binding EmployeeId}"/>
<GridViewColumn Header="Date"
DisplayMemberBinding="{Binding Date}"/>
<GridViewColumn Header="Time"
DisplayMemberBinding="{Binding Time}"/>
</GridView>
</ListView.View>
</ListView>
到目前为止,没有了普通。 但是,这是我与他们无关的代码。
属性:
private string[] _years;
public string[] Years
{
get { return _years; }
private set
{
if (_years == value)
{
return;
}
_years = value;
OnPropertyChanged("Years");
}
}
private int[] _yearCounts;
public int[] YearCounts
{
get { return _yearCounts; }
private set
{
if (_yearCounts == value)
{
return;
}
_yearCounts = value;
OnPropertyChanged("YearCounts");
}
}
private ObservableCollection<RecordModel> _missingCollection;
public ObservableCollection<RecordModel> MissingCollection
{
get { return _missingCollection; }
private set
{
if (_missingCollection == value)
{
return;
}
_missingCollection = value;
OnPropertyChanged("MissingCollection");
}
}
构造函数:
public MissingReportsViewModel()
{
YearCounts = new int[4];
Years = new string[4];
Task.Run(() =>
{
SetYears();
MissingCollection = new AccessWorker().GetMissingReports();
SetYearCounts();
});
}
从这个方法ViewModel
:
private void SetYears()
{
for (int i = 0; i < 4; i++)
{
Years[i] = DateTime.Now.AddYears(-i).Year.ToString();
}
}
private void SetYearCounts()
{
for (int i = 0; i < 4; i++)
{
YearCounts[i] = MissingCollection.Where(item => item.RepNum.Substring(0, 4).Equals(Years[i]))
.ToList().Count();
}
}
还有还有从接入辅助方法,但代码是相当长的。 它基本上连接到Access数据库,并得到了一些数据。
所以,我的问题是,如果我把之前的任何方法MissingCollection = new AccessWorker().GetMissingReports();
内部Task.Run()
或在它之外,他们将得到显示在UI。 不过,如果我那部分后放置任何物品,它不会显示在用户界面。 不要紧,下面的方法是内Task.Run
与否,同样的结果。 我检查和方法产量正确的价值观,他们只是从来没有使它的UI。 我只是不明白怎么这两个能产生如此不同的结果:
// First - Years get displayed.
// Second - After a little while data gets displayed
// Third - Counts never get displayed.
Task.Run(() =>
{
SetYears();
MissingCollection = new AccessWorker().GetMissingReports();
SetYearCounts();
});
// First - After a while, data gets displayed.
// Second - Years and counts do not get displayed.
Task.Run(() =>
{
MissingCollection = new AccessWorker().GetMissingReports();
SetYears();
SetYearCounts();
});
我明明做错事,但我想不出什么。 我试过调用到UI线程,但没有做任何事情。
编辑:
当我尝试调用一个更新到我的UI线程YearsCount
阵列绑定,我得到一个奇怪的超出范围的异常。 下面的代码:
private void Initialize()
{
SetYears();
Task.Run(() =>
{
MissingCollection = new AccessWorker().GetMissingReports();
SetYearCounts();
});
}
private void SetYearCounts()
{
for (int i = 0; i < 4; i++)
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => YearCounts[i] = MissingCollection.Where(
item => item.RepNum.Substring(0, 4).Equals(Years[i])).ToList().Count()));
}
}
当我通过它一步,它会经过YearCounts [I]的各项指标,跳出SetYearCounts的()返回Task.Run(),然后跳回SetYearsCounts(),并用最后i
值,是4年[I],其中,显然,投出范围的异常。
当我运行的代码,而无需Task.Run()这一切都不发生。 直到操作完成它只是冻结了UI。
如果我这样做:
private void Initialize()
{
SetYears();
Task.Run(() =>
{
MissingCollection = new AccessWorker().GetMissingReports();
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => SetYearCounts()));
});
}
......每个值写出来,因为它是在调试窗口被分配:
Debug.WriteLine(YearCounts[i]);
......它会在那儿写输出,而不是UI窗口。 我想它的事实,阵列只能靠自己改变报告和项目本身的不换做。 我可以看到,在调试窗口当只有阵列的初始初始化得到报告,但没有改变的项目。 但是,什么是奇怪的是,之前的观察集合任何更新,并且任何东西后不。 它有可能与查看其数据上下文时观察到的集合调用变化的观点做。
每个请求,这里的GetMissingReports()
声明部分:
public ObservableCollection<RecordModel> GetMissingReports() {..}