C# 使用IEnumerator是否是实现异步的最佳方法,而多线程似乎很慢?

C# 使用IEnumerator是否是实现异步的最佳方法,而多线程似乎很慢?,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,我试图创建某种框架,简化编写对象交互算法的过程。(一个对象--多个客户端(算法)) 例如,我想实现一个算法,该算法执行一些非常简单的工作,并在循环中等待某些条件满足: public void MakeVerySimpleJob() { } public void AsyncLoop() { // real algorithm can be more complex, but job is always very simple while (true) { Ma

我试图创建某种框架,简化编写对象交互算法的过程。(一个对象--多个客户端(算法))

  • 例如,我想实现一个算法,该算法执行一些非常简单的工作,并在循环中等待某些条件满足:

    public void MakeVerySimpleJob() { }
    
    public void AsyncLoop()
    { // real algorithm can be more complex, but job is always very simple
        while (true)
        {
            MakeVerySimpleJob();
            WakeUpCondition = "As fast as u can!";
            JobComplete.Set();
            WakeUp.WaitOne();
        }
    }
    
    void main()
    {
        Thread MyThread = new Thread(AsyncLoop);
        MyThread.Start();
    
        var w = new System.Diagnostics.Stopwatch(); w.Start();
        for (int i = 0; i < 100000; i++)
        {
            // waitin for thread
            JobComplete.WaitOne();
            // ok we did it
            WakeUpCondition = null;
            WakeUp.Set();
        }
        w.Stop();
    }
    
    AutoResetEvent JobComplete = new AutoResetEvent(false);
    AutoResetEvent WakeUp = new AutoResetEvent(false);
    
  • 所以我看一下
    枚举数。使用枚举器,用户可以以传统方式实现自己的算法:

    public IEnumerable<bool> PseudoAsyncLoop()
    {
        while (true)
        {
            MakeVerySimpleJob();
            WakeUpCondition = "As fast as u can!";
            yield return true;
        }
    }
    
    public string WakeUpCondition { get; private set; }
    
    void main()
    {
        var MyLoop = PseudoAsyncLoop();
        var LoopEnumerator = MyLoop.GetEnumerator();
    
        var w = new System.Diagnostics.Stopwatch(); w.Start();
        for(int i = 0; i < 100000; i ++)
        {
            LoopEnumerator.MoveNext();
            // ok we did it
            WakeUpCondition = null;
        }
        w.Stop();
    }
    
    public IEnumerable伪异步循环()
    {
    while(true)
    {
    MakeVerySimpleJob();
    WakeUpCondition=“尽可能快!”;
    收益率返回真;
    }
    }
    公共字符串唤醒条件{get;private set;}
    void main()
    {
    var MyLoop=PseudoAsyncLoop();
    var LoopEnumerator=MyLoop.GetEnumerator();
    var w=新系统。诊断。秒表();w.启动();
    对于(int i=0;i<100000;i++)
    {
    LoopEnumerator.MoveNext();
    //好的,我们做到了
    WakeUpCondition=null;
    }
    w、 停止();
    }
    
    现在大约需要
    3ms
    ,太好了。但我认为这一切都有问题

我的问题是:

  • 我的方向正确吗?
  • 专业程序员如何解决这类问题?
  • 是否有一些方法可以优化多线程版本?

我不完全理解您在做什么或为什么,但如果这实际上代表了您的代码,那么您可以使用
-Slim
同步原语之一来加速它,但是您可以使用
信号量lim

private readonly SemaphoreSlim JobComplete = new SemaphoreSlim(0, 1);
private readonly SemaphoreSlim WakeUp = new SemaphoreSlim(0, 1);

private void AsyncLoop()
{
    while (true)
    {
        MakeVerySimpleJob();
        WakeUpCondition = "As fast as u can!";
        JobComplete.Release();
        WakeUp.Wait();
    }
}

private void main()
{
    Thread MyThread = new Thread(AsyncLoop);
    MyThread.Start();

    for (int i = 0; i < 100000; i++)
    {
        JobComplete.Wait();
        WakeUpCondition = null;
        WakeUp.Release();
    }
}
private readonly信号量lim JobComplete=新信号量lim(0,1);
私有只读信号量lim WakeUp=新信号量lim(0,1);
私有void异步循环()
{
while(true)
{
MakeVerySimpleJob();
WakeUpCondition=“尽可能快!”;
JobComplete.Release();
醒醒,等等;
}
}
私有void main()
{
Thread MyThread=新线程(异步循环);
MyThread.Start();
对于(int i=0;i<100000;i++)
{
作业完成。等待();
WakeUpCondition=null;
WakeUp.Release();
}
}

这将使我的机器上的执行速度提高约5.5倍。

您是否考虑过以允许用户使用.NET framework中已有的并行编程功能的方式编写框架?你能更详细地描述一下你到底想做什么吗?为什么?例如,在您的代码中,两个“线程”都写入
WakeUpCondition
,但没有人读取它,这是没有意义的。另外,两个“线程”真的必须互相等待吗?其中一个线程不是一个“生产者”吗?它可以在其他线程使用它们之前产生一些项目?另外,您尝试做的事情与新的
async
/
wait
非常类似。你能升级到C#5.0吗?
private readonly SemaphoreSlim JobComplete = new SemaphoreSlim(0, 1);
private readonly SemaphoreSlim WakeUp = new SemaphoreSlim(0, 1);

private void AsyncLoop()
{
    while (true)
    {
        MakeVerySimpleJob();
        WakeUpCondition = "As fast as u can!";
        JobComplete.Release();
        WakeUp.Wait();
    }
}

private void main()
{
    Thread MyThread = new Thread(AsyncLoop);
    MyThread.Start();

    for (int i = 0; i < 100000; i++)
    {
        JobComplete.Wait();
        WakeUpCondition = null;
        WakeUp.Release();
    }
}