我正在编写一个基准测试工具,它从一个线程中的本地服务器读取一堆变量。
int countReads = 1000;
Int64 count = 0;
for (int i = 0; i < countReads; i++)
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
DateTime start = DateTime.Now;
session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos);
DateTime stop = DateTime.Now;
Thread.CurrentThread.Priority = ThreadPriority.Normal;
TimeSpan delay = (stop - start);
double s = delay.TotalMilliseconds;
count += (Int64)s;
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
progressBar1.Value = i;
}));
}
double avg = (double)count / countReads;
Dispatcher.Invoke(DispatcherPriority.Input, new Action(() =>
{
listBox1.Items.Add(avg);
}));
我正在计算进行阅读并在结束时获得平均时间跨度所花费的时间。
DateTime start = DateTime.Now;
session.Read(null, 0, TimestampsToReturn.Neither, idCollection, out ReadResults, out diagnosticInfos);
DateTime stop = DateTime.Now
如果我在不更新进度条的情况下运行代码,则平均花费大约5毫秒。 但如果我用
运行它 Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
progressBar1.Value = i;
}));
平均需要10毫秒。
我的问题是,为什么使用进度条时的时间跨度更高? 我只是计算阅读的时间跨度。不包括进度条更新。
有没有办法撤离ui画,这样才不会影响我的阅读时间?
感谢您的帮助。
祝你好运
答案 0 :(得分:8)
停止使用Invoke
将进度信息传输到UI线程。将进度信息发布到共享数据结构或变量,并在合理的时间间隔内使用计时器对其进行UI线程轮询。我知道似乎我们都被洗脑了以为Invoke
是进行工人到UI线程交互的全部方法,但对于简单的进度信息,它可能(通常是)最糟糕的方法。
在UI线程上使用计时器的轮询方法具有以下优点。
Invoke
对UI和工作线程施加的紧密耦合。我知道这并没有直接回答你的问题,为什么session.Read
似乎运行得更慢。尝试更改策略,以便将推送模型(通过Invoke
)更新进度信息到拉模型(通过计时器)。看看是否有所作为。即使它没有,我仍然会坚持拉模型,原因如上所示。
答案 1 :(得分:2)
以下是MSDN对Dispatcher.Invoke
所说的内容在与Dispatcher关联的线程上执行指定的委托同步。
因此,基本上,Dispatcher.Invoke
会阻塞,直到调度程序线程处理请求为止。
请尝试Dispatcher.BeginInvoke
。
答案 2 :(得分:0)
如果当前正在执行的线程与您正在使用的Dispatcher相关联 - Invoke()
将阻止此线程,因此在这种情况下尝试使用Dispatcher.BeginInvoke()它将异步执行此任务。
MSDN, Dispatcher.Invoke Method:
Invoke是一个同步操作;因此,控制权不会返回 调用对象直到回调返回之后。
顺便说一句,感兴趣的是DispatcherPriority.Send