我想在ListBox
中插入很多元素,我可以获得尽可能多的响应。为此我设置了一个生成string
s的生成器。我想在100毫秒窗口中添加新项目,而不是阻止UI并使用某种任务池(在当前情况下为Scheduler.Default
)。
Reactive浮现在我的脑海中,因为它符合每一项要求。
// Use binding, rather than control.Items.Add, so the elements can be added on simultanious tasks, without working on the Form's thread.
private readonly BindingList<string> elements = new BindingList<string>();
private void button1_Click(object sender, EventArgs e)
{
BindingSource source = new BindingSource {DataSource = elements};
listBox1.DataSource = source;
// works, but this way the window is useless.
//listBox1.BeginUpdate();
// generates 500 items to add into the listbox
Observable.Generate(0L, x => x < 500, x => x + 1,
y => "Current thread : " + Thread.CurrentThread.ManagedThreadId) // show which thread the item is generated
.Window(TimeSpan.FromSeconds(0.1d)) // supposedly makes UI unblock every 100 millisec
.ObserveOn(Scheduler.Default) // supposedly generate elements on the "thread pool"
.Subscribe(
x =>
{
x.Subscribe(s => elements.Add(s));
} /* , () =>
{
// for this we need System.Reactive.Windows.Forms
ControlScheduler scheduler = new ControlScheduler(this);
scheduler.Schedule(TimeSpan.FromSeconds(0L), () => listBox1.EndUpdate());
} */);
}
我的问题是,它为每一行显示相同的线程ID。因此,Scheduler.Default
上不会生成元素。我希望能够每100毫米改变焦点,但不能正常工作。
修改
我也尝试过后台工作者方法
private void button2_Click(object sender, EventArgs eventArgs)
{
// tried with elements volatile.
BindingSource source = new BindingSource {DataSource = elements};
listBox1.DataSource = source;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Observable.Generate(0L, x => x < 500, x => x + 1,
y => "Current thread : " + Thread.CurrentThread.ManagedThreadId)
.Window(TimeSpan.FromSeconds(0.1d))
.ObserveOn(Scheduler.Default)
.Subscribe(
window =>
{
window.Subscribe(s => elements.Add(s),
() => backgroundWorker1.ReportProgress(1)
);
});
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// doesn't work. No elements showing. Something must be notified, but couldn't make it working
listBox1.Refresh();
}
这种方法差别不大,只需要后台工作者的样板代码,并保证不会阻止UI。