【问题标题】:Synchronizing thread communication?同步线程通信?
【发布时间】:2011-02-11 01:50:28
【问题描述】:

只是为了它,我试图模拟 JRuby 生成器是如何使用 C# 中的线程工作的。

另外,我完全知道 C# 已经内置了对收益返回的支持,我只是在玩弄。

我猜这是通过使用线程保持多个调用堆栈处于活动状态的某种可怜的协程。 (即使任何调用堆栈都不应该同时执行)

思路是这样的:

  • 消费者线程请求一个值
  • 工作线程提供一个值并返回给消费者线程
  • 重复直到工作线程完成

那么,执行以下操作的正确方法是什么?

//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;
    }
}

想法?

【问题讨论】:

  • 您的代码看起来总体上是正确的。不过,我没有给太多时间,所以可能会有一些小错误,但总体看起来不错。你觉得它有什么问题吗?你有什么问题?
  • 主要问题是;有没有更好的方法来完成同样的事情,而无需求助于内置的 c# yield return 状态机?关于代码,它在某些情况下会挂起,如果嵌套枚举器,则性能极差。我对线程一无所知,所以我不太知道该怎么做

标签: c# multithreading jruby generator coroutine


【解决方案1】:

有很多方法可以在 C# 中实现生产者/消费者模式。 我猜最好的方法是使用 TPL (Task, BlockingCollection)。查看示例here

【讨论】:

    猜你喜欢
    • 2012-03-06
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 2015-07-06
    • 1970-01-01
    相关资源
    最近更新 更多