2010-04-22 58 views
1

只是爲了它,我試圖模仿JRuby生成器如何使用C#中的線程工作。另外,我完全意識到C#已經內置了對yield yield的支持,我只是玩弄了一下。同步線程通信?

我想通過使用線程保持多個調用堆棧存活,這是某種可憐的人協程。 (即使沒有調用堆棧應在同一時間執行)

的想法是這樣的:

  • 消費者線程請求
  • 工作者線程提供的值,併產生回值消費者線程
  • 重複,直到工作者線程完成

那麼,什麼會做下列的正確方法是什麼?

//example 
class Program 
{ 
    static void Main(string[] args) 
    { 
     ThreadedEnumerator<string> enumerator = new ThreadedEnumerator<string>(); 

     enumerator.Init(() => 
      { 
       for (int i = 1; i < 100; i++) 
       { 
        enumerator.Yield(i.ToString()); 
       } 
      }); 

     foreach (var item in enumerator) 
     { 
      Console.WriteLine(item); 
     }; 

     Console.ReadLine(); 
    } 
} 

//naive threaded enumerator 
public class ThreadedEnumerator<T> : IEnumerator<T>, IEnumerable<T> 
{ 
    private Thread enumeratorThread; 
    private T current; 
    private bool hasMore = true; 
    private bool isStarted = false; 
    AutoResetEvent enumeratorEvent = new AutoResetEvent(false); 
    AutoResetEvent consumerEvent = new AutoResetEvent(false); 
    public void Yield(T item) 
    { 
     //wait for consumer to request a value 
     consumerEvent.WaitOne(); 

     //assign the value 
     current = item; 

     //signal that we have yielded the requested 
     enumeratorEvent.Set(); 
    } 

    public void Init(Action userAction) 
    { 
     Action WrappedAction =() => 
     { 
      userAction(); 
      consumerEvent.WaitOne(); 
      enumeratorEvent.Set(); 
      hasMore = false; 
     }; 
     ThreadStart ts = new ThreadStart(WrappedAction); 
     enumeratorThread = new Thread(ts); 
     enumeratorThread.IsBackground = true; 
     isStarted = false; 
    } 

    public T Current 
    { 
     get { return current; } 
    } 

    public void Dispose() 
    { 
     enumeratorThread.Abort(); 
    } 

    object System.Collections.IEnumerator.Current 
    { 
     get { return Current; } 
    } 

    public bool MoveNext() 
    { 
     if (!isStarted) 
     { 
      isStarted = true; 
      enumeratorThread.Start(); 
     } 
     //signal that we are ready to receive a value 
     consumerEvent.Set(); 

     //wait for the enumerator to yield 
     enumeratorEvent.WaitOne(); 

     return hasMore; 
    } 

    public void Reset() 
    { 
     throw new NotImplementedException(); 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return this; 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return this; 
    } 
} 

想法?

+1

您的代碼似乎總體正確。但是我沒有花太多時間,所以可能會有一些小錯誤,但整體看起來不錯。你看到它有什麼問題嗎?你有什麼問題? – 2010-04-22 13:23:57

+0

主要問題是;有沒有更好的方法來完成相同的W/O訴諸內置的C#收益返回狀態機?關於代碼,它在某些情況下會掛起,並且如果嵌套枚舉器,則執行得非常糟糕。在線程方面我毫無頭緒,所以我不知道該怎麼做 – 2010-04-22 13:39:04

回答

0

有許多方法可以在C#中實現生產者/消費者模式。 我猜,最好的方法是使用TPL(Task,BlockingCollection)。看一個例子here