Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#为长期等待而等待_C#_.net_Multithreading - Fatal编程技术网

C#为长期等待而等待

C#为长期等待而等待,c#,.net,multithreading,C#,.net,Multithreading,此代码消耗接近零的CPU(i5系列) public void SpinWait(){ 对于(int i=0;i { var sw=新的SpinWait(); while(true) { sw.SpinOnce(); } }); } } 在我的代码中,当旋转是真正合理的(5个Mops)时,与信号量LIM相比,性能差异是3倍或更多。然而,我担心使用它进行长期等待。标准建议是实施两阶段等待操作。我可以检查NextSpinWillYield属性,并引入计数器+重置来增加默认的旋转迭代次数,而不产生屈服

此代码消耗接近零的CPU(i5系列)

public void SpinWait(){
对于(int i=0;i<10000;i++)
{
Task.Factory.StartNew(()=>
{
var sw=新的SpinWait();
while(true)
{
sw.SpinOnce();
}
});
}
}
在我的代码中,当旋转是真正合理的(5个Mops)时,与信号量LIM相比,性能差异是3倍或更多。然而,我担心使用它进行长期等待。标准建议是实施两阶段等待操作。我可以检查
NextSpinWillYield
属性,并引入计数器+重置来增加默认的旋转迭代次数,而不产生屈服,然后返回到信号量

但是,对于长期等待,只使用
SpinWait.SpinOnce
有什么缺点呢?我已经检查了它,它在需要的时候会适当地让步。它使用
Thread.SpinWait
,它在现代CPU上使用暂停指令,并且根据需要非常有效

我在监视任务管理器时发现的一个问题是,由于默认的线程池算法,线程数量会逐渐增加(当所有任务都很忙时,它会每秒添加一个线程)。这可以通过使用
ThreadPool.SetMaxThreads
来解决,然后线程数是固定的,CPU使用率仍然接近于零

如果长时间等待任务的数量是有限的,那么使用
SpinWait.SpinOnce
进行长时间等待还有哪些陷阱。它是否取决于CPU系列、OS、.NET版本


(只是澄清一下:我仍然会实现两阶段等待,我只是好奇为什么不一直使用SpinOnce?

好吧,缺点就是你所看到的,你的代码占用了一个线程而没有完成任何事情。阻止其他代码运行并强制threadpool管理器对此执行操作。TraceMulththRead()是一种创伤性伤口的创可贴,只有在你需要赶回家的时候才用它。 只有当您能够很好地保证旋转比线程上下文切换更有效时,才应该尝试旋转。这意味着您必须确保线程可以在大约10000个cpu周期或更少的时间内继续运行。这仅仅是5微秒,给出或取走,整个HekkFoalt比大多数程序员认为的“长期”要少。 使用将触发线程上下文切换的同步对象。或
锁定
关键字


这不仅会产生处理器,使其他等待线程能够完成任务,从而完成更多的工作,还为OS线程调度程序提供了一个极好的提示。发出信号的同步对象将影响线程的优先级,因此很可能会获得下一个处理器。

谢谢!顺便问一下,线程唤醒需要多少微秒,例如,如果我等待
信号量.WaitAsync(-1,token)
?如果我使用spinwait,并且
SpinOne
产生
Sleep(1)
,那么在最坏的情况下,如果信号正好在调用
Sleep(1)
之后到达,我会引入
至少
15毫秒的延迟。相反,如果我切换到信号量,线程在
信号量.Release()
之后唤醒的最坏情况延迟是多少?这在很大程度上取决于机器上发生的其他情况。当然,您还必须与其他进程和内核线程拥有的线程竞争。它需要微秒,而不是毫秒。只要用秒表测量,一定要取许多测量值的中间值,因为偶尔最坏的情况可能会很长。请记住,你对此无能为力,因此它只是一种信息。永远不要使用Sleep()。所以在信号量释放后醒来与.NET无关,使用C/C++甚至汇编也没有帮助?(不打算使用它们,只是为了理解这是硬件/操作系统设计)正确,线程调度和上下文切换是纯操作系统的职责,
    public void SpinWait() {

        for (int i = 0; i < 10000; i++)
        {
            Task.Factory.StartNew(() =>
            {
                var sw = new SpinWait();
                while (true)
                {
                    sw.SpinOnce();
                }
            });
        }
    }