在线程中,当循环次数太多时,Invoke浪费了很多时间

时间:2014-04-15 09:31:02

标签: multithreading performance delegates invoke

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);
循环中我什么都不做,但也浪费了很多时间!

为什么线程Event.Invoke花了这么多时间?

1 个答案:

答案 0 :(得分: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而不是Invoke来确保工作线程不会等待threadEvent完成(PostMessage行为)。这在这里工作得很好,因为你需要的threadEvent没有返回值。