2014-12-23 81 views
0

我想补充项目的大数目的ListBox
首先我定义它抱到了特定
项目对象添加到列表框项集合
这是实现基于任务的异步方法的正确方法吗?

delegate void D(); 

然后匿名方法的引用委托我写异步方法

private async void AddAsync() 
{ 

     await Task.Run(() => 
      { 
       for (int i = 0; i < 40000; i++) 
       { 
        D r = new D(() => this.listBox1.Items.Add(i)); 
        this.listBox1.Invoke(r); 
       } 
      } 
      ); 
} 

这是实施TAP的正确方法吗?
我犯了一个错误吗?
从性能的角度来看,你能提出一个更好的逻辑吗?或者这已经足够好了

+1

有40,000个项目的列表框?我不确定这是否会飞,但如果坚持我认为最好创建一个任务,将40,000个项目添加到列表框中,而不是创建40,000个任务,每个任务将单个项目添加到列表框中。 –

+0

哦,我犯了一个大错,我编辑了方法,谢谢 –

+0

从性能的角度来看,这可能是你能做的最糟糕的事情。正如Martin所说,由于您正在更新必须在UI线程上完成的UI,因此在UI线程的单线程循环中执行此操作会更有效率。在UI环境中,一般来说,当这些长时间运行的操作的结果可用时,您希望将长时间运行的非UI相关**任务转移到后台,并且只在UI线程上调用它们,但在更新这种UI时,您最好在主线程中完成,而不是创建40,000个任务来完成它。 – kha

回答

1

正如其他人在评论中提到的那样,整个后台线程的要点是做后台工作。在你的例子中,没有后台工作。整个后台代理只是将工作发送到UI线程。

如果这实际上是代表你的代码,你可能也只是做它直接在UI线程:

private void Add() 
{ 
    for (int i = 0; i < 40000; i++) 
    this.listBox1.Items.Add(i); 
} 

注意加入项目的UI是UI操作,所以必须在UI线程上完成。现在,如果创建项目需要一定的时间,那么你可以从后台的工作中受益:

private async Task AddAsync() 
{ 
    IProgress<int> progress = new Progress<int>(x => this.listBox1.Items.Add(x)); 
    await Task.Run(() => 
    { 
    for (int i = 0; i < 40000; i++) 
    { 
     int value = i; // TODO: replace this with the long-running create-item code. 
     progress.Report(value); 
    } 
    }); 
} 

注意使用IProgress<T>/Progress<T>避免过时Control.Invoke机制。

+0

谢谢,我想如果我使用后台线程,那么UI线程将不会做任何工作,对于这种误解抱歉,请你解释为什么使用后台线程进行需要时间的操作是有用的,因为在任何情况下UI线程将收到更新其控件的请求?我测试的代码与依赖于UI线程的代码差别很大 –

+0

@MadMass:后台线程对于在另一个线程上执行*非UI工作*很有用。因此,如果需要花费一秒左右来创建每个项目,那么可以通过后台线程完成该工作,而UI线程只需要花费10ms左右的时间来添加项目。 –

相关问题