如何将此C#工作线程代码与主线程中的共享数据变量分离?

时间:2010-08-09 04:23:51

标签: c# .net multithreading dependency-injection code-readability

为了更好的代码可读性,我怎么能修改下面的代码呢?

a)将“workThreadMethod()”移动到它自己的类

b)此工作线程类中没有任何代码引用主“程序”类

中的静态变量 c)以上是主要的两个要求,但是我希望作为副作用,这将确保为了可测试性,工作者线程类方法将更容易测试并且理想地适合通过IOC进行测试(例如,Ninject)概念[如果这没有意义,那么为了问题的目的忽略这一点]

我不确定要解决的主要挑战是如何处理原始线程和发起线程之间的两个不同的共享变量。新线程(其中一个是新线程添加的ConcurrentQueue,另一个是原始线程用来指示新线程何时停止的bool变量)

using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;

namespace TestConsoleApp
{
    class Program
    {
        // Main Thread uses to indicate to New Thread to stop
        private static bool _shouldStop = false;

        // New Thread uses to pass back result to Main Thread
        private static long _results = 0;

        // Main Thread passes ongoing updates to New Thread via this queue
        private static ConcurrentQueue<long> _workQueue = new ConcurrentQueue<long>();

        static void Main(string[] args)
        {
            var p = new Program();
            p.TestThreads();
        }

        public void TestThreads()
        {
            _shouldStop = false;
            var workThread = new Thread(workThreadMethod);
            workThread.Start();

            for (int i = 0; i < 100; i++)
            {
                _workQueue.Enqueue(i);   // Add test data to queue
                Debug.WriteLine("Queue  : " + i);
                Thread.Sleep(10);
            }

            Thread.Sleep(5000);

            _shouldStop = true;
            workThread.Join();
            Debug.WriteLine("Finished TestThreads.  Result = " + _results);
        }


        // Dequeuer Methods
        private void workThreadMethod()
        {
            // Update Summary
            while (!_shouldStop)
            {
                if (_workQueue.Count == 0)
                {
                    Thread.Sleep(10);
                }
                else
                {
                    long currentValue;
                    bool worked = _workQueue.TryDequeue(out currentValue);
                    if (worked)
                    {
                        _results += currentValue;
                        Debug.WriteLine("DeQueue: " + currentValue);
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

这是关注点分离的练习,最初我会将此计划拆分为work providerworker。提供者负责队列和执行控制,而工作人员应该进行计算。以下代码是一个粗略的开始,但它应该让你去。

分解这两个问题并使用构造函数注入已经支付了可测试性,现在您可以完全测试Worker而不涉及Program

注意:考虑进一步开发您的应用,我强烈建议您查看the Task Parallel Library。使用诸如TPL之类的库使您可以利用多核处理器,而无需处理线程分配和工作调度的复杂性。讨论了有关TPL的更多资源here

public interface IWorkProvider
{
    bool ShouldStop { get; }
    long? GetWork();
}

public class Program : IWorkProvider
{
    // Main Thread uses to indicate to New Thread to stop
    private static bool _shouldStop = false;

    // Main Thread passes ongoing updates to New Thread via this queue
    private static ConcurrentQueue<long> _workQueue = new ConcurrentQueue<long>();

    public bool ShouldStop { get { return _shouldStop; } }

    public long? GetWork()
    {
        long currentValue;
        bool worked = _workQueue.TryDequeue(out currentValue);
        if (worked)
            return currentValue;
        return null;
    }
}

public class Worker
{
    private long _results;
    private readonly IWorkProvider _workProvider;

    public long Results { get { return _results; }}

    public Worker(IWorkProvider workProvider)
    {
        _workProvider = workProvider;
    }

    public void DoWork()
    {
        // Update Summary
        while (!_workProvider.ShouldStop)
        {
            long? work = _workProvider.GetWork();
            if (work.HasValue)
            {
                _results += work.Value;
                Debug.WriteLine("DeQueue: " + work.Value);
            }
            else
            {
                Thread.Sleep(10);
            }
        }
    }

}