0

I am trying to create some kind of framework that simplifies process of writing object interaction algorithm. (One object -- many clients(algorithms))

  • For example I want to implement algorithm that do some very simple job and waits some condition meet in a loop:

    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);
    

    Unfortunately it consumes about 500ms to do 100000 simple jobs.

  • Ok multithreading is not acceptable in my case, but I dont want to force users to write algorithms in this manner:

    // invoke it again and again
    public void PseudoAsyncLoop()
    {
        if (CurrentState == 1) 
        {
            MakeVerySimpleJob();
            CurrentState = 2;
            return;
        }
        else is (CurrentState == some_sate)
        {
        }
    }
    
    int CurrentState = 0;
    
  • So i look at Enumerators. With Enumerators user can implement their own algorithm in traditional style:

    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();
    }
    

    Now it takes about 3ms, great. But i think its something wrong with that all...

My questions is:

  • Am I in right direction?
  • How does professional programmers solves that types of problems?
  • May be there is some ways to optimize multithreaded version?
user990095
  • 23
  • 5
  • 2
    Have you thought about writing your framework in a way that simply allows your users to use the parallel programming features that are already available in the .NET Framework? http://msdn.microsoft.com/en-us/library/dd460693.aspx – Robert Harvey Jan 30 '13 at 18:50
  • Could you describe in more detail what exactly are you trying to do any why? For example, in your code, both “threads” write to `WakeUpCondition`, but no one ever reads it, that doesn't make sense. Also, do both “threads” really have to wait on each other? Isn't one of the threads a “producer”, which could produce a few items before they are consumed by the other thread? – svick Jan 30 '13 at 19:18
  • Also, what you're trying to do is very similar to the new `async`/`await`. Can you upgrade to C# 5.0? – svick Jan 30 '13 at 19:19

1 Answers1

1

I don't completely understand what are you doing or why, but if this is actually representative of your code, then you can speed it up by using one of the -Slim synchronization primitives. There is no AutoResetEventSlim, but you can use SemaphoreSlim instead:

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();
    }
}

This results in about 5.5× faster execution on my machine.

Community
  • 1
  • 1
svick
  • 236,525
  • 50
  • 385
  • 514