2014-04-15 23 views
-1
for (int i = 0; i < 100,000; i++) 
{ 
    threadEvent.Invoke(i, new EventArgs());// tell processbar value 
} 

threadEvent += new EventHandler(method_threadEvent); 
void method_threadEvent(object sender, EventArgs e) 
    { 
     int nowValue = Convert.ToInt32(sender); 
     nowValueDelegate now = new nowValueDelegate(setNow); 
     this.Invoke(now, nowValue); 
    } 
private void setNow(int nowValue) 
    { 
     this.progressBar1.Value = nowValue; 
    } 
private delegate void nowValueDelegate(int nowValue); 
在环我什么都不做

,但同时也浪费了大量的时间!在线程,当循环太多时间,调用浪费了大量的时间

为什么threadEvent.Invoke花这么多时间?

+0

这是不正确的,“在循环中我什么都不做”;你正在调用'threadEvent.Invoke'。事实上,这是你做的唯一的事情,所以当然这需要100%的时间。 –

+0

这只是一个例子,我删除了其他代码,当更新进程栏时,如果我不使用调用,它会占用太多时间,实际上它可以很快完成。 – user1908725

+1

你想听什么?正如你发现的那样,调用是昂贵的。不经常调用。进度条不必更新100K次。每100ms更新一次。 – usr

回答

0

调用是一项昂贵的操作,因为它必须跨越线程边界。

最好减少调用的数量,例如只更新工作的每个百分比的进度条,而不是循环的每次迭代。这样,只需要处理100个更新,而不是每个迭代一个。

您需要做的第一件事就是计算或估计当前的进度。 对于典型的循环

for (int i = 0; i < someValue; ++i) 
{ 
    ... // Work here 
} 

进步的良好估计是(i/someValue) * 100,这给已完成循环的百分比。要更新进度,只有在下一比例已经达到了,你可以在该行做一些UI线程:

int percentCompleted = 0; 
threadEvent.Invoke(percentCompleted, new EventArgs()); // Initial progressbar value 
for (int i = 0; i < someValue; ++i) 
{ 
    int newlyCompleted = (i/someValue) * 100; 
    if (newlyCompleted > percentCompleted) 
      threadEvent.Invoke(percentCompleted, new EventArgs()); 
    percentCompleted = newlyCompleted; 

    ... // Work here 
} 

如今终于,你可以使用的BeginInvoke,而不是调用,以确保工作线程没有按”等待threadEvent完成(PostMessage行为)。这在这里很有效,因为你不需要threadEvent的返回值。

+0

正如你所说,有没有办法避免?这是一个很好的方法,每100 updata updata进程条,但数据num是未知的。 – user1908725

+0

@ user1908725:您需要计算或估算工作线程中的进度百分比。然后,每当您的百分比增加1或更多时,就调用更新。这减少了需要发送的更新数量,这是一件好事 - 您想要执行工作,而不是花时间更新。为了进一步提高性能,可以使用BeginInvoke,而不是Invoke:调用块并等待UI线程完成更新,而BeginInvoke发布消息并立即连续。 – MicroVirus

+0

@ user1908725:我编辑了我的答案,用一些示例代码来解答您的问题 – MicroVirus